add support for AWS Organizations
endpoints covers so far: - create_organization - describe_organization - create_account - describe_account - list_accounts all tests passing. could use some advise from maintaners.
This commit is contained in:
		
							parent
							
								
									a1d095c14b
								
							
						
					
					
						commit
						edbc57e00d
					
				| @ -27,6 +27,7 @@ from .glacier import mock_glacier, mock_glacier_deprecated  # flake8: noqa | ||||
| from .iam import mock_iam, mock_iam_deprecated  # flake8: noqa | ||||
| from .kinesis import mock_kinesis, mock_kinesis_deprecated  # flake8: noqa | ||||
| from .kms import mock_kms, mock_kms_deprecated  # flake8: noqa | ||||
| from .organizations import mock_organizations  # flake8: noqa | ||||
| from .opsworks import mock_opsworks, mock_opsworks_deprecated  # flake8: noqa | ||||
| from .polly import mock_polly  # flake8: noqa | ||||
| from .rds import mock_rds, mock_rds_deprecated  # flake8: noqa | ||||
|  | ||||
| @ -26,6 +26,7 @@ from moto.kinesis import kinesis_backends | ||||
| from moto.kms import kms_backends | ||||
| from moto.logs import logs_backends | ||||
| from moto.opsworks import opsworks_backends | ||||
| from moto.organizations import organizations_backends | ||||
| from moto.polly import polly_backends | ||||
| from moto.rds2 import rds2_backends | ||||
| from moto.redshift import redshift_backends | ||||
| @ -72,6 +73,7 @@ BACKENDS = { | ||||
|     'kinesis': kinesis_backends, | ||||
|     'kms': kms_backends, | ||||
|     'opsworks': opsworks_backends, | ||||
|     'organizations': organizations_backends, | ||||
|     'polly': polly_backends, | ||||
|     'redshift': redshift_backends, | ||||
|     'rds': rds2_backends, | ||||
|  | ||||
							
								
								
									
										6
									
								
								moto/organizations/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								moto/organizations/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| from __future__ import unicode_literals | ||||
| from .models import organizations_backend | ||||
| from ..core.models import base_decorator | ||||
| 
 | ||||
| organizations_backends = {"global": organizations_backend} | ||||
| mock_organizations = base_decorator(organizations_backends) | ||||
							
								
								
									
										131
									
								
								moto/organizations/models.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								moto/organizations/models.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,131 @@ | ||||
| from __future__ import unicode_literals | ||||
| 
 | ||||
| import datetime | ||||
| import time | ||||
| 
 | ||||
| from moto.core import BaseBackend, BaseModel | ||||
| from moto.core.utils import unix_time | ||||
| from moto.organizations import utils | ||||
| 
 | ||||
| MASTER_ACCOUNT_ID = '123456789012' | ||||
| MASTER_ACCOUNT_EMAIL = 'fakeorg@moto-example.com' | ||||
| ORGANIZATION_ARN_FORMAT = 'arn:aws:organizations::{0}:organization/{1}' | ||||
| MASTER_ACCOUNT_ARN_FORMAT = 'arn:aws:organizations::{0}:account/{1}/{0}' | ||||
| ACCOUNT_ARN_FORMAT = 'arn:aws:organizations::{0}:account/{1}/{2}' | ||||
| 
 | ||||
| 
 | ||||
| class FakeOrganization(BaseModel): | ||||
| 
 | ||||
|     def __init__(self, feature_set): | ||||
|         self.id = utils.make_random_org_id() | ||||
|         self.feature_set = feature_set | ||||
|         self.master_account_id = MASTER_ACCOUNT_ID | ||||
|         self.master_account_email = MASTER_ACCOUNT_EMAIL | ||||
|         self.available_policy_types = [{ | ||||
|             'Type': 'SERVICE_CONTROL_POLICY', | ||||
|             'Status': 'ENABLED' | ||||
|         }] | ||||
|      | ||||
|     @property | ||||
|     def arn(self): | ||||
|         return ORGANIZATION_ARN_FORMAT.format(self.master_account_id, self.id) | ||||
| 
 | ||||
|     @property | ||||
|     def master_account_arn(self): | ||||
|         return MASTER_ACCOUNT_ARN_FORMAT.format(self.master_account_id, self.id) | ||||
| 
 | ||||
|     def _describe(self): | ||||
|         return { | ||||
|             'Organization': { | ||||
|                 'Id': self.id, | ||||
|                 'Arn': self.arn, | ||||
|                 'FeatureSet': self.feature_set, | ||||
|                 'MasterAccountArn': self.master_account_arn, | ||||
|                 'MasterAccountId': self.master_account_id, | ||||
|                 'MasterAccountEmail': self.master_account_email, | ||||
|                 'AvailablePolicyTypes': self.available_policy_types, | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
| class FakeAccount(BaseModel): | ||||
| 
 | ||||
|     def __init__(self, organization, **kwargs): | ||||
|         self.organization_id = organization.id | ||||
|         self.master_account_id = organization.master_account_id | ||||
|         self.create_account_status_id = utils.make_random_create_account_status_id() | ||||
|         self.account_id = utils.make_random_account_id() | ||||
|         self.account_name = kwargs['AccountName'] | ||||
|         self.email = kwargs['Email'] | ||||
|         self.create_time = datetime.datetime.utcnow() | ||||
|         self.status = 'ACTIVE' | ||||
|         self.joined_method = 'CREATED' | ||||
| 
 | ||||
|     @property | ||||
|     def arn(self): | ||||
|         return ACCOUNT_ARN_FORMAT.format( | ||||
|             self.master_account_id, | ||||
|             self.organization_id, | ||||
|             self.account_id | ||||
|         ) | ||||
| 
 | ||||
|     @property | ||||
|     def create_account_status(self): | ||||
|         return { | ||||
|             'CreateAccountStatus': { | ||||
|                 'Id': self.create_account_status_id, | ||||
|                 'AccountName': self.account_name, | ||||
|                 'State': 'SUCCEEDED', | ||||
|                 'RequestedTimestamp': unix_time(self.create_time), | ||||
|                 'CompletedTimestamp': unix_time(self.create_time), | ||||
|                 'AccountId': self.account_id, | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|     def describe(self): | ||||
|         return { | ||||
|             'Account': { | ||||
|                 'Id': self.account_id, | ||||
|                 'Arn': self.arn, | ||||
|                 'Email': self.email, | ||||
|                 'Name': self.account_name, | ||||
|                 'Status': self.status, | ||||
|                 'JoinedMethod': self.joined_method, | ||||
|                 'JoinedTimestamp': unix_time(self.create_time), | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
| class OrganizationsBackend(BaseBackend): | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         self.org = None | ||||
|         self.accounts = [] | ||||
| 
 | ||||
|     def create_organization(self, **kwargs): | ||||
|         self.org = FakeOrganization(kwargs['FeatureSet']) | ||||
|         return self.org._describe() | ||||
| 
 | ||||
|     def describe_organization(self): | ||||
|         return self.org._describe() | ||||
| 
 | ||||
|     def create_account(self, **kwargs): | ||||
|         new_account = FakeAccount(self.org, **kwargs) | ||||
|         self.accounts.append(new_account) | ||||
|         return new_account.create_account_status | ||||
| 
 | ||||
|     def describe_account(self, **kwargs): | ||||
|         account = [account for account in self.accounts  | ||||
|                    if account.account_id == kwargs['AccountId']][0] | ||||
|         return account.describe() | ||||
| 
 | ||||
|     def list_accounts(self): | ||||
|         return dict( | ||||
|             Accounts=[account.describe()['Account'] for account in self.accounts] | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
| organizations_backend = OrganizationsBackend() | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										48
									
								
								moto/organizations/responses.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								moto/organizations/responses.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,48 @@ | ||||
| from __future__ import unicode_literals | ||||
| import json | ||||
| 
 | ||||
| from moto.core.responses import BaseResponse | ||||
| from .models import organizations_backend | ||||
| 
 | ||||
| 
 | ||||
| class OrganizationsResponse(BaseResponse): | ||||
| 
 | ||||
|     @property | ||||
|     def organizations_backend(self): | ||||
|         return organizations_backend | ||||
| 
 | ||||
|     @property | ||||
|     def request_params(self): | ||||
|         try: | ||||
|             return json.loads(self.body) | ||||
|         except ValueError: | ||||
|             return {} | ||||
| 
 | ||||
|     def _get_param(self, param, default=None): | ||||
|         return self.request_params.get(param, default) | ||||
| 
 | ||||
|     def create_organization(self): | ||||
|         return json.dumps( | ||||
|             self.organizations_backend.create_organization(**self.request_params) | ||||
|         ) | ||||
| 
 | ||||
|     def describe_organization(self): | ||||
|         return json.dumps( | ||||
|             self.organizations_backend.describe_organization() | ||||
|         ) | ||||
| 
 | ||||
|     def create_account(self): | ||||
|         return json.dumps( | ||||
|             self.organizations_backend.create_account(**self.request_params) | ||||
|         ) | ||||
| 
 | ||||
|     def describe_account(self): | ||||
|         return json.dumps( | ||||
|             self.organizations_backend.describe_account(**self.request_params) | ||||
|         ) | ||||
| 
 | ||||
|     def list_accounts(self): | ||||
|         return json.dumps( | ||||
|             self.organizations_backend.list_accounts() | ||||
|         ) | ||||
| 
 | ||||
							
								
								
									
										10
									
								
								moto/organizations/urls.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								moto/organizations/urls.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| from __future__ import unicode_literals | ||||
| from .responses import OrganizationsResponse | ||||
| 
 | ||||
| url_bases = [ | ||||
|     "https?://organizations.(.+).amazonaws.com", | ||||
| ] | ||||
| 
 | ||||
| url_paths = { | ||||
|     '{0}/$': OrganizationsResponse.dispatch, | ||||
| } | ||||
							
								
								
									
										34
									
								
								moto/organizations/utils.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								moto/organizations/utils.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | ||||
| from __future__ import unicode_literals | ||||
| 
 | ||||
| import random | ||||
| import string | ||||
| 
 | ||||
| CHARSET=string.ascii_lowercase + string.digits | ||||
| ORG_ID_SIZE = 10 | ||||
| ROOT_ID_SIZE = 4 | ||||
| ACCOUNT_ID_SIZE = 12 | ||||
| CREATE_ACCOUNT_STATUS_ID_SIZE = 8 | ||||
| 
 | ||||
| 
 | ||||
| def make_random_org_id(): | ||||
|     # The regex pattern for an organization ID string requires "o-"  | ||||
|     # followed by from 10 to 32 lower-case letters or digits. | ||||
|     # e.g. 'o-vipjnq5z86' | ||||
|     return 'o-' + ''.join(random.choice(CHARSET) for x in range(ORG_ID_SIZE)) | ||||
| 
 | ||||
| def make_random_root_id(): | ||||
|     # The regex pattern for a root ID string requires "r-" followed by  | ||||
|     # from 4 to 32 lower-case letters or digits. | ||||
|     # e.g. 'r-3zwx' | ||||
|     return 'r-' + ''.join(random.choice(CHARSET) for x in range(ROOT_ID_SIZE)) | ||||
| 
 | ||||
| def make_random_account_id(): | ||||
|     # The regex pattern for an account ID string requires exactly 12 digits. | ||||
|     # e.g. '488633172133' | ||||
|     return ''.join([random.choice(string.digits) for n in range(ACCOUNT_ID_SIZE)]) | ||||
| 
 | ||||
| def make_random_create_account_status_id(): | ||||
|     # The regex pattern for an create account request ID string requires  | ||||
|     # "car-" followed by from 8 to 32 lower-case letters or digits. | ||||
|     # e.g. 'car-35gxzwrp' | ||||
|     return 'car-' + ''.join(random.choice(CHARSET) for x in range(CREATE_ACCOUNT_STATUS_ID_SIZE)) | ||||
							
								
								
									
										0
									
								
								tests/test_organizations/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								tests/test_organizations/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										24
									
								
								tests/test_organizations/object_syntax.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								tests/test_organizations/object_syntax.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| """ | ||||
| Temporary functions for checking object structures while specing out | ||||
| models.  This module will go away. | ||||
| """ | ||||
| 
 | ||||
| import yaml | ||||
| import moto | ||||
| from moto import organizations as orgs | ||||
| 
 | ||||
| 
 | ||||
| # utils | ||||
| print(orgs.utils.make_random_org_id()) | ||||
| print(orgs.utils.make_random_root_id()) | ||||
| print(orgs.utils.make_random_account_id()) | ||||
| print(orgs.utils.make_random_create_account_id()) | ||||
| 
 | ||||
| # models | ||||
| my_org = orgs.models.FakeOrganization(feature_set = 'ALL') | ||||
| print(yaml.dump(my_org._describe())) | ||||
| #assert False | ||||
| 
 | ||||
| my_account = orgs.models.FakeAccount(my_org, AccountName='blee01', Email='blee01@moto-example.org') | ||||
| print(yaml.dump(my_account)) | ||||
| #assert False | ||||
							
								
								
									
										193
									
								
								tests/test_organizations/test_organizations_boto3.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								tests/test_organizations/test_organizations_boto3.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,193 @@ | ||||
| from __future__ import unicode_literals | ||||
| 
 | ||||
| import boto3 | ||||
| import botocore.exceptions | ||||
| import sure   # noqa | ||||
| import yaml | ||||
| import re | ||||
| import datetime | ||||
| 
 | ||||
| import moto | ||||
| from moto import mock_organizations | ||||
| from moto.organizations.models import ( | ||||
|     MASTER_ACCOUNT_ID, | ||||
|     MASTER_ACCOUNT_EMAIL, | ||||
|     ORGANIZATION_ARN_FORMAT, | ||||
|     MASTER_ACCOUNT_ARN_FORMAT, | ||||
|     ACCOUNT_ARN_FORMAT, | ||||
| ) | ||||
| from .test_organizations_utils import ( | ||||
|     ORG_ID_REGEX, | ||||
|     ROOT_ID_REGEX, | ||||
|     ACCOUNT_ID_REGEX, | ||||
|     CREATE_ACCOUNT_STATUS_ID_REGEX, | ||||
| ) | ||||
| 
 | ||||
| EMAIL_REGEX = "^.+@[a-zA-Z0-9-.]+.[a-zA-Z]{2,3}|[0-9]{1,3}$" | ||||
| 
 | ||||
| 
 | ||||
| def validate_organization(response): | ||||
|     org = response['Organization'] | ||||
|     sorted(org.keys()).should.equal([ | ||||
|         'Arn', | ||||
|         'AvailablePolicyTypes', | ||||
|         'FeatureSet', | ||||
|         'Id', | ||||
|         'MasterAccountArn', | ||||
|         'MasterAccountEmail', | ||||
|         'MasterAccountId', | ||||
|     ]) | ||||
|     org['Id'].should.match(ORG_ID_REGEX) | ||||
|     org['MasterAccountId'].should.equal(MASTER_ACCOUNT_ID) | ||||
|     org['MasterAccountArn'].should.equal(MASTER_ACCOUNT_ARN_FORMAT.format( | ||||
|         org['MasterAccountId'], | ||||
|         org['Id'], | ||||
|     )) | ||||
|     org['Arn'].should.equal(ORGANIZATION_ARN_FORMAT.format( | ||||
|         org['MasterAccountId'], | ||||
|         org['Id'], | ||||
|     )) | ||||
|     org['MasterAccountEmail'].should.equal(MASTER_ACCOUNT_EMAIL) | ||||
|     org['FeatureSet'].should.be.within(['ALL', 'CONSOLIDATED_BILLING']) | ||||
|     org['AvailablePolicyTypes'].should.equal([{ | ||||
|         'Type': 'SERVICE_CONTROL_POLICY', | ||||
|         'Status': 'ENABLED' | ||||
|     }]) | ||||
|     # | ||||
|     #'Organization': { | ||||
|     #    'Id': 'string', | ||||
|     #    'Arn': 'string', | ||||
|     #    'FeatureSet': 'ALL'|'CONSOLIDATED_BILLING', | ||||
|     #    'MasterAccountArn': 'string', | ||||
|     #    'MasterAccountId': 'string', | ||||
|     #    'MasterAccountEmail': 'string', | ||||
|     #    'AvailablePolicyTypes': [ | ||||
|     #        { | ||||
|     #            'Type': 'SERVICE_CONTROL_POLICY', | ||||
|     #            'Status': 'ENABLED'|'PENDING_ENABLE'|'PENDING_DISABLE' | ||||
|     #        }, | ||||
|     #    ] | ||||
|     #} | ||||
| 
 | ||||
| def validate_account(org, account): | ||||
|     sorted(account.keys()).should.equal([ | ||||
|         'Arn', | ||||
|         'Email', | ||||
|         'Id', | ||||
|         'JoinedMethod', | ||||
|         'JoinedTimestamp', | ||||
|         'Name', | ||||
|         'Status', | ||||
|     ]) | ||||
|     account['Id'].should.match(ACCOUNT_ID_REGEX) | ||||
|     account['Arn'].should.equal(ACCOUNT_ARN_FORMAT.format( | ||||
|         org['MasterAccountId'], | ||||
|         org['Id'], | ||||
|         account['Id'], | ||||
|     ))         | ||||
|     account['Email'].should.match(EMAIL_REGEX) | ||||
|     account['JoinedMethod'].should.be.within(['INVITED', 'CREATED']) | ||||
|     account['Status'].should.be.within(['ACTIVE', 'SUSPENDED']) | ||||
|     account['Name'].should.be.a(str) | ||||
|     account['JoinedTimestamp'].should.be.a(datetime.datetime) | ||||
|     #'Account': { | ||||
|     #    'Id': 'string', | ||||
|     #    'Arn': 'string', | ||||
|     #    'Email': 'string', | ||||
|     #    'Name': 'string', | ||||
|     #    'Status': 'ACTIVE'|'SUSPENDED', | ||||
|     #    'JoinedMethod': 'INVITED'|'CREATED', | ||||
|     #    'JoinedTimestamp': datetime(2015, 1, 1) | ||||
|     #} | ||||
| 
 | ||||
| def validate_create_account_status(create_status): | ||||
|     sorted(create_status.keys()).should.equal([ | ||||
|         'AccountId', | ||||
|         'AccountName', | ||||
|         'CompletedTimestamp', | ||||
|         'Id', | ||||
|         'RequestedTimestamp', | ||||
|         'State', | ||||
|     ]) | ||||
|     create_status['Id'].should.match(CREATE_ACCOUNT_STATUS_ID_REGEX) | ||||
|     create_status['AccountId'].should.match(ACCOUNT_ID_REGEX) | ||||
|     create_status['AccountName'].should.be.a(str) | ||||
|     create_status['State'].should.equal('SUCCEEDED') | ||||
|     create_status['RequestedTimestamp'].should.be.a(datetime.datetime) | ||||
|     create_status['CompletedTimestamp'].should.be.a(datetime.datetime) | ||||
|     #'CreateAccountStatus': { | ||||
|     #    'Id': 'string', | ||||
|     #    'AccountName': 'string', | ||||
|     #    'State': 'IN_PROGRESS'|'SUCCEEDED'|'FAILED', | ||||
|     #    'RequestedTimestamp': datetime(2015, 1, 1), | ||||
|     #    'CompletedTimestamp': datetime(2015, 1, 1), | ||||
|     #    'AccountId': 'string', | ||||
|     #    'FailureReason': 'ACCOUNT_LIMIT_EXCEEDED'|'EMAIL_ALREADY_EXISTS'|'INVALID_ADDRESS'|'INVALID_EMAIL'|'CONCURRENT_ACCOUNT_MODIFICATION'|'INTERNAL_FAILURE' | ||||
|     #} | ||||
| 
 | ||||
| @mock_organizations | ||||
| def test_create_organization(): | ||||
|     client = boto3.client('organizations', region_name='us-east-1') | ||||
|     response = client.create_organization(FeatureSet='ALL') | ||||
|     #print(yaml.dump(response)) | ||||
|     validate_organization(response) | ||||
|     response['Organization']['FeatureSet'].should.equal('ALL') | ||||
|     #assert False | ||||
| 
 | ||||
| @mock_organizations | ||||
| def test_describe_organization(): | ||||
|     client = boto3.client('organizations', region_name='us-east-1') | ||||
|     client.create_organization(FeatureSet='ALL') | ||||
|     response = client.describe_organization() | ||||
|     #print(yaml.dump(response)) | ||||
|     validate_organization(response) | ||||
|     #assert False | ||||
| 
 | ||||
| 
 | ||||
| mockname = 'mock-account' | ||||
| mockdomain = 'moto-example.org' | ||||
| mockemail = '@'.join([mockname, mockdomain]) | ||||
| 
 | ||||
| @mock_organizations | ||||
| def test_create_account(): | ||||
|     client = boto3.client('organizations', region_name='us-east-1') | ||||
|     client.create_organization(FeatureSet='ALL') | ||||
|     create_status = client.create_account( | ||||
|             AccountName=mockname, Email=mockemail)['CreateAccountStatus'] | ||||
|     #print(yaml.dump(create_status, default_flow_style=False)) | ||||
|     validate_create_account_status(create_status) | ||||
|     create_status['AccountName'].should.equal(mockname) | ||||
|     #assert False | ||||
| 
 | ||||
| @mock_organizations | ||||
| def test_describe_account(): | ||||
|     client = boto3.client('organizations', region_name='us-east-1') | ||||
|     org = client.create_organization(FeatureSet='ALL')['Organization'] | ||||
|     account_id = client.create_account( | ||||
|             AccountName=mockname, Email=mockemail)['CreateAccountStatus']['AccountId'] | ||||
|     response = client.describe_account(AccountId=account_id) | ||||
|     #print(yaml.dump(response, default_flow_style=False)) | ||||
|     validate_account(org, response['Account']) | ||||
|     response['Account']['Name'].should.equal(mockname) | ||||
|     response['Account']['Email'].should.equal(mockemail) | ||||
|     #assert False | ||||
| 
 | ||||
| @mock_organizations | ||||
| def test_list_accounts(): | ||||
|     client = boto3.client('organizations', region_name='us-east-1') | ||||
|     org = client.create_organization(FeatureSet='ALL')['Organization'] | ||||
|     for i in range(5): | ||||
|         name = mockname + str(i) | ||||
|         email = name + '@' + mockdomain | ||||
|         client.create_account(AccountName=name, Email=email) | ||||
|     response = client.list_accounts() | ||||
|     #print(yaml.dump(response, default_flow_style=False)) | ||||
|     response.should.have.key('Accounts') | ||||
|     accounts = response['Accounts'] | ||||
|     len(accounts).should.equal(5) | ||||
|     for account in accounts: | ||||
|         validate_account(org, account) | ||||
|     accounts[3]['Name'].should.equal(mockname + '3') | ||||
|     accounts[2]['Email'].should.equal(mockname + '2' + '@' + mockdomain) | ||||
|     #assert False | ||||
| 
 | ||||
							
								
								
									
										26
									
								
								tests/test_organizations/test_organizations_utils.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								tests/test_organizations/test_organizations_utils.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| from __future__ import unicode_literals | ||||
| 
 | ||||
| import sure   # noqa | ||||
| import moto | ||||
| from moto.organizations import utils | ||||
| 
 | ||||
| ORG_ID_REGEX = r'o-[a-z0-9]{%s}' % utils.ORG_ID_SIZE | ||||
| ROOT_ID_REGEX = r'r-[a-z0-9]{%s}' % utils.ROOT_ID_SIZE | ||||
| ACCOUNT_ID_REGEX = r'[0-9]{%s}' % utils.ACCOUNT_ID_SIZE | ||||
| CREATE_ACCOUNT_STATUS_ID_REGEX = r'car-[a-z0-9]{%s}' % utils.CREATE_ACCOUNT_STATUS_ID_SIZE | ||||
| 
 | ||||
| def test_make_random_org_id(): | ||||
|     org_id = utils.make_random_org_id() | ||||
|     org_id.should.match(ORG_ID_REGEX) | ||||
| 
 | ||||
| def test_make_random_root_id(): | ||||
|     org_id = utils.make_random_root_id() | ||||
|     org_id.should.match(ROOT_ID_REGEX) | ||||
| 
 | ||||
| def test_make_random_account_id(): | ||||
|     account_id = utils.make_random_account_id() | ||||
|     account_id.should.match(ACCOUNT_ID_REGEX) | ||||
| 
 | ||||
| def test_make_random_create_account_status_id(): | ||||
|     create_account_status_id = utils.make_random_create_account_status_id() | ||||
|     create_account_status_id.should.match(CREATE_ACCOUNT_STATUS_ID_REGEX) | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user