organizations: endpoint list_parents now support account_id param

refactered classes: FakeRoot inherits from FakeOrganizationsUnit
add root_id attribute to class FakeOrganization
dropped 'roots' attribute from class OrganizationaBackend
This commit is contained in:
Ashley Gould 2018-07-15 20:39:13 -07:00
parent 9b5c6c4f0f
commit 30a9aa33e5
2 changed files with 98 additions and 65 deletions

View File

@ -1,6 +1,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import datetime import datetime
import re
from moto.core import BaseBackend, BaseModel from moto.core import BaseBackend, BaseModel
from moto.core.utils import unix_time from moto.core.utils import unix_time
@ -19,6 +20,7 @@ class FakeOrganization(BaseModel):
def __init__(self, feature_set): def __init__(self, feature_set):
self.id = utils.make_random_org_id() self.id = utils.make_random_org_id()
self.root_id = utils.make_random_root_id()
self.feature_set = feature_set self.feature_set = feature_set
self.master_account_id = MASTER_ACCOUNT_ID self.master_account_id = MASTER_ACCOUNT_ID
self.master_account_email = MASTER_ACCOUNT_EMAIL self.master_account_email = MASTER_ACCOUNT_EMAIL
@ -51,7 +53,7 @@ class FakeOrganization(BaseModel):
class FakeAccount(BaseModel): class FakeAccount(BaseModel):
def __init__(self, organization, root_id, **kwargs): def __init__(self, organization, **kwargs):
self.organization_id = organization.id self.organization_id = organization.id
self.master_account_id = organization.master_account_id self.master_account_id = organization.master_account_id
self.create_account_status_id = utils.make_random_create_account_status_id() self.create_account_status_id = utils.make_random_create_account_status_id()
@ -61,7 +63,7 @@ class FakeAccount(BaseModel):
self.create_time = datetime.datetime.utcnow() self.create_time = datetime.datetime.utcnow()
self.status = 'ACTIVE' self.status = 'ACTIVE'
self.joined_method = 'CREATED' self.joined_method = 'CREATED'
self.parent_id = root_id self.parent_id = organization.root_id
@property @property
def arn(self): def arn(self):
@ -100,16 +102,18 @@ class FakeAccount(BaseModel):
class FakeOrganizationalUnit(BaseModel): class FakeOrganizationalUnit(BaseModel):
def __init__(self, organization, root_id, **kwargs): def __init__(self, organization, **kwargs):
self.type = 'ORGANIZATIONAL_UNIT'
self.organization_id = organization.id self.organization_id = organization.id
self.master_account_id = organization.master_account_id self.master_account_id = organization.master_account_id
self.id = utils.make_random_ou_id(root_id) self.id = utils.make_random_ou_id(organization.root_id)
self.name = kwargs['Name'] self.name = kwargs.get('Name')
self.parent_id = kwargs['ParentId'] self.parent_id = kwargs.get('ParentId')
self._arn_format = OU_ARN_FORMAT
@property @property
def arn(self): def arn(self):
return OU_ARN_FORMAT.format( return self._arn_format.format(
self.master_account_id, self.master_account_id,
self.organization_id, self.organization_id,
self.id self.id
@ -125,25 +129,18 @@ class FakeOrganizationalUnit(BaseModel):
} }
class FakeRoot(BaseModel): class FakeRoot(FakeOrganizationalUnit):
def __init__(self, organization, **kwargs): def __init__(self, organization, **kwargs):
self.organization_id = organization.id super().__init__(organization, **kwargs)
self.master_account_id = organization.master_account_id self.type = 'ROOT'
self.id = utils.make_random_root_id() self.id = organization.root_id
self.name = 'Root' self.name = 'Root'
self.policy_types = [{ self.policy_types = [{
'Type': 'SERVICE_CONTROL_POLICY', 'Type': 'SERVICE_CONTROL_POLICY',
'Status': 'ENABLED' 'Status': 'ENABLED'
}] }]
self._arn_format = ROOT_ARN_FORMAT
@property
def arn(self):
return ROOT_ARN_FORMAT.format(
self.master_account_id,
self.organization_id,
self.id
)
def describe(self): def describe(self):
return { return {
@ -154,18 +151,16 @@ class FakeRoot(BaseModel):
} }
class OrganizationsBackend(BaseBackend): class OrganizationsBackend(BaseBackend):
def __init__(self): def __init__(self):
self.org = None self.org = None
self.accounts = [] self.accounts = []
self.roots = []
self.ou = [] self.ou = []
def create_organization(self, **kwargs): def create_organization(self, **kwargs):
self.org = FakeOrganization(kwargs['FeatureSet']) self.org = FakeOrganization(kwargs['FeatureSet'])
self.roots.append(FakeRoot(self.org)) self.ou.append(FakeRoot(self.org))
return self.org.describe() return self.org.describe()
def describe_organization(self): def describe_organization(self):
@ -173,11 +168,11 @@ class OrganizationsBackend(BaseBackend):
def list_roots(self): def list_roots(self):
return dict( return dict(
Roots=[root.describe() for root in self.roots] Roots=[ou.describe() for ou in self.ou if isinstance(ou, FakeRoot)]
) )
def create_organizational_unit(self, **kwargs): def create_organizational_unit(self, **kwargs):
new_ou = FakeOrganizationalUnit(self.org, self.roots[0].id, **kwargs) new_ou = FakeOrganizationalUnit(self.org, **kwargs)
self.ou.append(new_ou) self.ou.append(new_ou)
return new_ou.describe() return new_ou.describe()
@ -201,23 +196,29 @@ class OrganizationsBackend(BaseBackend):
) )
def list_parents(self, **kwargs): def list_parents(self, **kwargs):
parent_id = [ if re.compile(r'[0-9]{12}').match(kwargs['ChildId']):
ou.parent_id for ou in self.ou if ou.id == kwargs['ChildId'] parent_id = [
].pop(0) account.parent_id for account in self.accounts
root_parents = [ if account.id == kwargs['ChildId']
dict(Id=root.id, Type='ROOT') ].pop(0)
for root in self.roots else:
if root.id == parent_id parent_id = [
] ou.parent_id for ou in self.ou
ou_parents = [ if ou.id == kwargs['ChildId']
dict(Id=ou.id, Type='ORGANIZATIONAL_UNIT') ].pop(0)
for ou in self.ou return dict(
if ou.id == parent_id Parents=[
] {
return dict(Parents=root_parents + ou_parents) 'Id': ou.id,
'Type': ou.type,
}
for ou in self.ou
if ou.id == parent_id
]
)
def create_account(self, **kwargs): def create_account(self, **kwargs):
new_account = FakeAccount(self.org, self.roots[0].id, **kwargs) new_account = FakeAccount(self.org, **kwargs)
self.accounts.append(new_account) self.accounts.append(new_account)
return new_account.create_account_status return new_account.create_account_status
@ -244,9 +245,10 @@ class OrganizationsBackend(BaseBackend):
def move_account(self, **kwargs): def move_account(self, **kwargs):
new_parent_id = kwargs['DestinationParentId'] new_parent_id = kwargs['DestinationParentId']
all_parent_id = [parent.id for parent in self.roots + self.ou] all_parent_id = [parent.id for parent in self.ou]
account = [ account = [
account for account in self.accounts if account.id == kwargs['AccountId'] account for account in self.accounts
if account.id == kwargs['AccountId']
].pop(0) ].pop(0)
assert new_parent_id in all_parent_id assert new_parent_id in all_parent_id
assert account.parent_id == kwargs['SourceParentId'] assert account.parent_id == kwargs['SourceParentId']

View File

@ -198,30 +198,6 @@ def test_list_organizational_units_for_parent():
#assert False #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
# Accounts # Accounts
mockname = 'mock-account' mockname = 'mock-account'
mockdomain = 'moto-example.org' mockdomain = 'moto-example.org'
@ -310,3 +286,58 @@ def test_move_account():
#print(yaml.dump(response, default_flow_style=False)) #print(yaml.dump(response, default_flow_style=False))
account_id.should.be.within([account['Id'] for account in response['Accounts']]) account_id.should.be.within([account['Id'] for account in response['Accounts']])
#assert False #assert False
@mock_organizations
def test_list_parents_for_ou():
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
@mock_organizations
def test_list_parents_for_accounts():
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']
account01_id = client.create_account(
AccountName='account01',
Email='account01@moto-example.org'
)['CreateAccountStatus']['AccountId']
account02_id = client.create_account(
AccountName='account02',
Email='account02@moto-example.org'
)['CreateAccountStatus']['AccountId']
client.move_account(
AccountId=account02_id,
SourceParentId=root_id,
DestinationParentId=ou01_id,
)
response01 = client.list_parents(ChildId=account01_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')
response02 = client.list_parents(ChildId=account02_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