Repository: getmoto/moto

Issue:
Organizations: create_organization fails to add master account and default policy to mock organization
the mock organization does not contain the master account or the default policy.  After running
create_organization, the list_accounts and list_policies methods each return an empty list.


Discussion:
patch forthcoming

Resolving patch:
diff --git a/moto/organizations/models.py b/moto/organizations/models.py
--- a/moto/organizations/models.py
+++ b/moto/organizations/models.py
@@ -2,6 +2,7 @@
 
 import datetime
 import re
+import json
 
 from moto.core import BaseBackend, BaseModel
 from moto.core.exceptions import RESTError
@@ -151,7 +152,6 @@ def describe(self):
 class FakeServiceControlPolicy(BaseModel):
 
     def __init__(self, organization, **kwargs):
-        self.type = 'POLICY'
         self.content = kwargs.get('Content')
         self.description = kwargs.get('Description')
         self.name = kwargs.get('Name')
@@ -197,7 +197,38 @@ def __init__(self):
 
     def create_organization(self, **kwargs):
         self.org = FakeOrganization(kwargs['FeatureSet'])
-        self.ou.append(FakeRoot(self.org))
+        root_ou = FakeRoot(self.org)
+        self.ou.append(root_ou)
+        master_account = FakeAccount(
+            self.org,
+            AccountName='master',
+            Email=self.org.master_account_email,
+        )
+        master_account.id = self.org.master_account_id
+        self.accounts.append(master_account)
+        default_policy = FakeServiceControlPolicy(
+            self.org,
+            Name='FullAWSAccess',
+            Description='Allows access to every operation',
+            Type='SERVICE_CONTROL_POLICY',
+            Content=json.dumps(
+                {
+                    "Version": "2012-10-17",
+                    "Statement": [
+                        {
+                            "Effect": "Allow",
+                            "Action": "*",
+                            "Resource": "*"
+                        }
+                    ]
+                }
+            )
+        )
+        default_policy.id = utils.DEFAULT_POLICY_ID
+        default_policy.aws_managed = True
+        self.policies.append(default_policy)
+        self.attach_policy(PolicyId=default_policy.id, TargetId=root_ou.id)
+        self.attach_policy(PolicyId=default_policy.id, TargetId=master_account.id)
         return self.org.describe()
 
     def describe_organization(self):
@@ -216,6 +247,7 @@ def list_roots(self):
     def create_organizational_unit(self, **kwargs):
         new_ou = FakeOrganizationalUnit(self.org, **kwargs)
         self.ou.append(new_ou)
+        self.attach_policy(PolicyId=utils.DEFAULT_POLICY_ID, TargetId=new_ou.id)
         return new_ou.describe()
 
     def get_organizational_unit_by_id(self, ou_id):
@@ -258,6 +290,7 @@ def list_organizational_units_for_parent(self, **kwargs):
     def create_account(self, **kwargs):
         new_account = FakeAccount(self.org, **kwargs)
         self.accounts.append(new_account)
+        self.attach_policy(PolicyId=utils.DEFAULT_POLICY_ID, TargetId=new_account.id)
         return new_account.create_account_status
 
     def get_account_by_id(self, account_id):
@@ -358,8 +391,7 @@ def describe_policy(self, **kwargs):
 
     def attach_policy(self, **kwargs):
         policy = next((p for p in self.policies if p.id == kwargs['PolicyId']), None)
-        if (re.compile(utils.ROOT_ID_REGEX).match(kwargs['TargetId']) or
-                re.compile(utils.OU_ID_REGEX).match(kwargs['TargetId'])):
+        if (re.compile(utils.ROOT_ID_REGEX).match(kwargs['TargetId']) or re.compile(utils.OU_ID_REGEX).match(kwargs['TargetId'])):
             ou = next((ou for ou in self.ou if ou.id == kwargs['TargetId']), None)
             if ou is not None:
                 if ou not in ou.attached_policies:
diff --git a/moto/organizations/utils.py b/moto/organizations/utils.py
--- a/moto/organizations/utils.py
+++ b/moto/organizations/utils.py
@@ -4,7 +4,8 @@
 import string
 
 MASTER_ACCOUNT_ID = '123456789012'
-MASTER_ACCOUNT_EMAIL = 'fakeorg@moto-example.com'
+MASTER_ACCOUNT_EMAIL = 'master@example.com'
+DEFAULT_POLICY_ID = 'p-FullAWSAccess'
 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}'
@@ -26,7 +27,7 @@
 OU_ID_REGEX = r'ou-[a-z0-9]{%s}-[a-z0-9]{%s}' % (ROOT_ID_SIZE, OU_ID_SUFFIX_SIZE)
 ACCOUNT_ID_REGEX = r'[0-9]{%s}' % ACCOUNT_ID_SIZE
 CREATE_ACCOUNT_STATUS_ID_REGEX = r'car-[a-z0-9]{%s}' % CREATE_ACCOUNT_STATUS_ID_SIZE
-SCP_ID_REGEX = r'p-[a-z0-9]{%s}' % SCP_ID_SIZE
+SCP_ID_REGEX = r'%s|p-[a-z0-9]{%s}' % (DEFAULT_POLICY_ID, SCP_ID_SIZE)
 
 
 def make_random_org_id():


Test patch:
diff --git a/tests/test_organizations/organizations_test_utils.py b/tests/test_organizations/organizations_test_utils.py
--- a/tests/test_organizations/organizations_test_utils.py
+++ b/tests/test_organizations/organizations_test_utils.py
@@ -1,7 +1,6 @@
 from __future__ import unicode_literals
 
 import six
-import sure   # noqa
 import datetime
 from moto.organizations import utils
 
diff --git a/tests/test_organizations/test_organizations_boto3.py b/tests/test_organizations/test_organizations_boto3.py
--- a/tests/test_organizations/test_organizations_boto3.py
+++ b/tests/test_organizations/test_organizations_boto3.py
@@ -3,7 +3,6 @@
 import boto3
 import json
 import six
-import sure   # noqa
 from botocore.exceptions import ClientError
 from nose.tools import assert_raises
 
@@ -27,6 +26,25 @@ def test_create_organization():
     validate_organization(response)
     response['Organization']['FeatureSet'].should.equal('ALL')
 
+    response = client.list_accounts()
+    len(response['Accounts']).should.equal(1)
+    response['Accounts'][0]['Name'].should.equal('master')
+    response['Accounts'][0]['Id'].should.equal(utils.MASTER_ACCOUNT_ID)
+    response['Accounts'][0]['Email'].should.equal(utils.MASTER_ACCOUNT_EMAIL)
+
+    response = client.list_policies(Filter='SERVICE_CONTROL_POLICY')
+    len(response['Policies']).should.equal(1)
+    response['Policies'][0]['Name'].should.equal('FullAWSAccess')
+    response['Policies'][0]['Id'].should.equal(utils.DEFAULT_POLICY_ID)
+    response['Policies'][0]['AwsManaged'].should.equal(True)
+
+    response = client.list_targets_for_policy(PolicyId=utils.DEFAULT_POLICY_ID)
+    len(response['Targets']).should.equal(2)
+    root_ou = [t for t in response['Targets'] if t['Type'] == 'ROOT'][0]
+    root_ou['Name'].should.equal('Root')
+    master_account = [t for t in response['Targets'] if t['Type'] == 'ACCOUNT'][0]
+    master_account['Name'].should.equal('master')
+
 
 @mock_organizations
 def test_describe_organization():
@@ -177,11 +195,11 @@ def test_list_accounts():
     response = client.list_accounts()
     response.should.have.key('Accounts')
     accounts = response['Accounts']
-    len(accounts).should.equal(5)
+    len(accounts).should.equal(6)
     for account in accounts:
         validate_account(org, account)
-    accounts[3]['Name'].should.equal(mockname + '3')
-    accounts[2]['Email'].should.equal(mockname + '2' + '@' + mockdomain)
+    accounts[4]['Name'].should.equal(mockname + '3')
+    accounts[3]['Email'].should.equal(mockname + '2' + '@' + mockdomain)
 
 
 @mock_organizations
@@ -291,8 +309,10 @@ def test_list_children():
     response02 = client.list_children(ParentId=root_id, ChildType='ORGANIZATIONAL_UNIT')
     response03 = client.list_children(ParentId=ou01_id, ChildType='ACCOUNT')
     response04 = client.list_children(ParentId=ou01_id, ChildType='ORGANIZATIONAL_UNIT')
-    response01['Children'][0]['Id'].should.equal(account01_id)
+    response01['Children'][0]['Id'].should.equal(utils.MASTER_ACCOUNT_ID)
     response01['Children'][0]['Type'].should.equal('ACCOUNT')
+    response01['Children'][1]['Id'].should.equal(account01_id)
+    response01['Children'][1]['Type'].should.equal('ACCOUNT')
     response02['Children'][0]['Id'].should.equal(ou01_id)
     response02['Children'][0]['Type'].should.equal('ORGANIZATIONAL_UNIT')
     response03['Children'][0]['Id'].should.equal(account02_id)
@@ -591,4 +611,3 @@ def test_list_targets_for_policy_exception():
     ex.operation_name.should.equal('ListTargetsForPolicy')
     ex.response['Error']['Code'].should.equal('400')
     ex.response['Error']['Message'].should.contain('InvalidInputException')
-