diff --git a/IMPLEMENTATION_COVERAGE.md b/IMPLEMENTATION_COVERAGE.md index 7b4bc5e4d..84c574bc3 100644 --- a/IMPLEMENTATION_COVERAGE.md +++ b/IMPLEMENTATION_COVERAGE.md @@ -3147,7 +3147,7 @@ - [ ] update_server - [ ] update_server_engine_attributes -## organizations - 19% implemented +## organizations - 20% implemented - [ ] accept_handshake - [ ] attach_policy - [ ] cancel_handshake @@ -3180,8 +3180,8 @@ - [ ] list_create_account_status - [ ] list_handshakes_for_account - [ ] list_handshakes_for_organization -- [ ] list_organizational_units_for_parent -- [ ] list_parents +- [X] list_organizational_units_for_parent +- [X] list_parents - [ ] list_policies - [ ] list_policies_for_target - [X] list_roots diff --git a/moto/organizations/models.py b/moto/organizations/models.py index 461072ce3..b46c62798 100644 --- a/moto/organizations/models.py +++ b/moto/organizations/models.py @@ -14,6 +14,7 @@ ACCOUNT_ARN_FORMAT = 'arn:aws:organizations::{0}:account/{1}/{2}' ROOT_ARN_FORMAT = 'arn:aws:organizations::{0}:root/{1}/{2}' OU_ARN_FORMAT = 'arn:aws:organizations::{0}:ou/{1}/{2}' + class FakeOrganization(BaseModel): def __init__(self, feature_set): @@ -125,7 +126,6 @@ class FakeRoot(BaseModel): } - class FakeOrganizationalUnit(BaseModel): def __init__(self, organization, root_id, **kwargs): @@ -152,6 +152,7 @@ class FakeOrganizationalUnit(BaseModel): } } + class OrganizationsBackend(BaseBackend): def __init__(self): @@ -184,6 +185,35 @@ class OrganizationsBackend(BaseBackend): ].pop(0) return ou.describe() + def list_organizational_units_for_parent(self, **kwargs): + return dict( + OrganizationalUnits=[ + { + 'Id': ou.id, + 'Arn': ou.arn, + 'Name': ou.name, + } + for ou in self.ou + if ou.parent_id == kwargs['ParentId'] + ] + ) + + def list_parents(self, **kwargs): + parent_id = [ + ou.parent_id for ou in self.ou if ou.id == kwargs['ChildId'] + ].pop(0) + root_parents = [ + dict(Id=root.id, Type='ROOT') + for root in self.roots + if root.id == parent_id + ] + ou_parents = [ + dict(Id=ou.id, Type='ORGANIZATIONAL_UNIT') + for ou in self.ou + if ou.id == parent_id + ] + return dict(Parents=root_parents + ou_parents) + def create_account(self, **kwargs): new_account = FakeAccount(self.org, **kwargs) self.accounts.append(new_account) diff --git a/moto/organizations/responses.py b/moto/organizations/responses.py index 4f0643cf6..9fdb73317 100644 --- a/moto/organizations/responses.py +++ b/moto/organizations/responses.py @@ -46,6 +46,16 @@ class OrganizationsResponse(BaseResponse): self.organizations_backend.describe_organizational_unit(**self.request_params) ) + def list_organizational_units_for_parent(self): + return json.dumps( + self.organizations_backend.list_organizational_units_for_parent(**self.request_params) + ) + + def list_parents(self): + return json.dumps( + self.organizations_backend.list_parents(**self.request_params) + ) + def create_account(self): return json.dumps( self.organizations_backend.create_account(**self.request_params) diff --git a/tests/test_organizations/test_organizations_boto3.py b/tests/test_organizations/test_organizations_boto3.py index 0e398bd43..8375ffbe3 100644 --- a/tests/test_organizations/test_organizations_boto3.py +++ b/tests/test_organizations/test_organizations_boto3.py @@ -55,7 +55,7 @@ def validate_organization(response): }]) -def validate_organizationa_unit(org, response): +def validate_organizational_unit(org, response): response.should.have.key('OrganizationalUnit').should.be.a(dict) ou = response['OrganizationalUnit'] ou.should.have.key('Id').should.match(OU_ID_REGEX) @@ -64,7 +64,7 @@ def validate_organizationa_unit(org, response): org['Id'], ou['Id'], )) - ou.should.have.key('Name').should.equal(ou_name) + ou.should.have.key('Name').should.be.a(str) def validate_account(org, account): @@ -128,7 +128,6 @@ def test_describe_organization(): # Organizational Units -ou_name = 'ou01' @mock_organizations def test_list_roots(): @@ -157,12 +156,14 @@ def test_create_organizational_unit(): client = boto3.client('organizations', region_name='us-east-1') org = client.create_organization(FeatureSet='ALL')['Organization'] root_id = client.list_roots()['Roots'][0]['Id'] + ou_name = 'ou01' response = client.create_organizational_unit( ParentId=root_id, Name=ou_name, ) #print(yaml.dump(response, default_flow_style=False)) - validate_organizationa_unit(org, response) + validate_organizational_unit(org, response) + response['OrganizationalUnit']['Name'].should.equal(ou_name) #assert False @@ -173,13 +174,51 @@ def test_describe_organizational_unit(): root_id = client.list_roots()['Roots'][0]['Id'] ou_id = client.create_organizational_unit( ParentId=root_id, - Name=ou_name, + Name='ou01', )['OrganizationalUnit']['Id'] - response = client.describe_organizational_unit( - OrganizationalUnitId=ou_id, - ) + response = client.describe_organizational_unit(OrganizationalUnitId=ou_id) print(yaml.dump(response, default_flow_style=False)) - validate_organizationa_unit(org, response) + validate_organizational_unit(org, response) + #assert False + + +@mock_organizations +def test_list_organizational_units_for_parent(): + client = boto3.client('organizations', region_name='us-east-1') + org = client.create_organization(FeatureSet='ALL')['Organization'] + root_id = client.list_roots()['Roots'][0]['Id'] + client.create_organizational_unit(ParentId=root_id, Name='ou01') + client.create_organizational_unit(ParentId=root_id, Name='ou02') + client.create_organizational_unit(ParentId=root_id, Name='ou03') + response = client.list_organizational_units_for_parent(ParentId=root_id) + print(yaml.dump(response, default_flow_style=False)) + response.should.have.key('OrganizationalUnits').should.be.a(list) + for ou in response['OrganizationalUnits']: + validate_organizational_unit(org, dict(OrganizationalUnit=ou)) + #assert False + + +@mock_organizations +def test_list_parents(): + client = boto3.client('organizations', region_name='us-east-1') + org = client.create_organization(FeatureSet='ALL')['Organization'] + root_id = client.list_roots()['Roots'][0]['Id'] + + ou01 = client.create_organizational_unit(ParentId=root_id, Name='ou01') + ou01_id = ou01['OrganizationalUnit']['Id'] + response01 = client.list_parents(ChildId=ou01_id) + #print(yaml.dump(response01, default_flow_style=False)) + response01.should.have.key('Parents').should.be.a(list) + response01['Parents'][0].should.have.key('Id').should.equal(root_id) + response01['Parents'][0].should.have.key('Type').should.equal('ROOT') + + ou02 = client.create_organizational_unit(ParentId=ou01_id, Name='ou02') + ou02_id = ou02['OrganizationalUnit']['Id'] + response02 = client.list_parents(ChildId=ou02_id) + #print(yaml.dump(response02, default_flow_style=False)) + response02.should.have.key('Parents').should.be.a(list) + response02['Parents'][0].should.have.key('Id').should.equal(ou01_id) + response02['Parents'][0].should.have.key('Type').should.equal('ORGANIZATIONAL_UNIT') #assert False