Repository: getmoto/moto

Issue:
iot.delete_thing_group() should raise when deleting groups with childs
Given the folowing group hierarchy:
```
--Group1a
    |--Group2a
```
When calling `iot.delete_group_thing("Group1a")`. The following error should rise:
`botocore.errorfactory.InvalidRequestException: An error occurred (InvalidRequestException) when calling the DeleteThingGroup operation: Cannot delete thing group : Group1a when there are still child groups attached to it`

However, moto just deletes the group succesfully.


Discussion:

Resolving patch:
diff --git a/moto/iot/models.py b/moto/iot/models.py
--- a/moto/iot/models.py
+++ b/moto/iot/models.py
@@ -842,6 +842,17 @@ def create_thing_group(
         return thing_group.thing_group_name, thing_group.arn, thing_group.thing_group_id
 
     def delete_thing_group(self, thing_group_name, expected_version):
+        child_groups = [
+            thing_group
+            for _, thing_group in self.thing_groups.items()
+            if thing_group.parent_group_name == thing_group_name
+        ]
+        if len(child_groups) > 0:
+            raise InvalidRequestException(
+                " Cannot delete thing group : "
+                + thing_group_name
+                + " when there are still child groups attached to it"
+            )
         thing_group = self.describe_thing_group(thing_group_name)
         del self.thing_groups[thing_group.arn]
 


Test patch:
diff --git a/tests/test_iot/test_iot.py b/tests/test_iot/test_iot.py
--- a/tests/test_iot/test_iot.py
+++ b/tests/test_iot/test_iot.py
@@ -756,6 +756,47 @@ def test_delete_principal_thing():
     client.delete_certificate(certificateId=cert_id)
 
 
+@mock_iot
+def test_delete_thing_group():
+    client = boto3.client("iot", region_name="ap-northeast-1")
+    group_name_1a = "my-group-name-1a"
+    group_name_2a = "my-group-name-2a"
+    # --1a
+    #    |--2a
+
+    # create thing groups tree
+    # 1
+    thing_group1a = client.create_thing_group(thingGroupName=group_name_1a)
+    thing_group1a.should.have.key("thingGroupName").which.should.equal(group_name_1a)
+    thing_group1a.should.have.key("thingGroupArn")
+    # 2
+    thing_group2a = client.create_thing_group(
+        thingGroupName=group_name_2a, parentGroupName=group_name_1a
+    )
+    thing_group2a.should.have.key("thingGroupName").which.should.equal(group_name_2a)
+    thing_group2a.should.have.key("thingGroupArn")
+
+    # delete group with child
+    try:
+        client.delete_thing_group(thingGroupName=group_name_1a)
+    except client.exceptions.InvalidRequestException as exc:
+        error_code = exc.response["Error"]["Code"]
+        error_code.should.equal("InvalidRequestException")
+    else:
+        raise Exception("Should have raised error")
+
+    # delete child group
+    client.delete_thing_group(thingGroupName=group_name_2a)
+    res = client.list_thing_groups()
+    res.should.have.key("thingGroups").which.should.have.length_of(1)
+    res["thingGroups"].should_not.have.key(group_name_2a)
+
+    # now that there is no child group, we can delete the previus group safely
+    client.delete_thing_group(thingGroupName=group_name_1a)
+    res = client.list_thing_groups()
+    res.should.have.key("thingGroups").which.should.have.length_of(0)
+
+
 @mock_iot
 def test_describe_thing_group_metadata_hierarchy():
     client = boto3.client("iot", region_name="ap-northeast-1")