Skip to content

Commit

Permalink
Merge pull request #123 from theserverlessway/feature/stack-set-regio…
Browse files Browse the repository at this point in the history
…n-account-options

Implement excluded regions and main account parameters
  • Loading branch information
flomotlik committed Mar 15, 2019
2 parents 470acc3 + d7b4d73 commit 9c82e7c
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 18 deletions.
5 changes: 3 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
language: python
dist: xenial
sudo: false

matrix:
include:
- python: '3.6'
- python: '3.7'
env:
- INTEGRATION_TEST=true
- AWS_DEFAULT_REGION=eu-central-1
Expand All @@ -15,7 +16,7 @@ matrix:
- AWS_DEFAULT_REGION=eu-central-1
- secure: k8/SQDpINDU/fRfYkgVjSyTTgXcuj4W3fcFso+SR8QkQAGF36QjLlNUUA42FLpm0mc1Xr4eCx7YKY4GUMqng5bSncWy/At5OAGLdt1RjG2KY1EhujFtUcW /Co8y2648vNzQrv5FtfIxHlN6OXRHoIAwtV7kNyKHFagunfGpuNqvkvo2Loj1JtqJdV60obG4x0w7dMaKhWWWxbzHs1jZrgyFhpv2508pWkhu/gE1iLlk0iOwNU6IShNRpUcrHfCYocCOyDiT1uiT+WkM14UIMusc1kXWPObcqvRHl84z5KDgAogm5Spc6ep00llh6br+XzL6XZEOkn7K4p0rxF0Z13qEP7OOPuVdx+rwPTUwXVPBH/T5GWC5pKnh1P2Osod73PRWMU2RuYyzWaP535LA/Ub7qlpk18DNyw9stuzZRdkPEwDvZzTkESsTHn8EWkMgB/hyyxK9aJFLoqqoivCNoACXhG96mBpTs0fbjd5swiYhMIT3W61Kmo5eOOyqctT6KV+UEq/+txTnrlt4WeuWYvlD7oJSAKP50l1cQEmVVx0Z3B0HfI7MbtWfzPjZ9a1j15zmKjVMcAvnk32m42d4MzwjYxGsGL5TAvlGvDPUjis3FxeSrDpNfvQkQljEux19E1VZrafqvWXJtfxai5EWU369Uxm5I4KoGlRY5PqAM8Mg=
- secure: cjYgJ3u0TD0zLfm+PgyCOcwE9ZnmKaM68QEF/JsCAkcD2iz8eYTssBIDMp988+YJHSltptOMBruzy33CnkC1AH6UV+Vp9OyBb38++/U1nUK0QEjZxWNuggDgRGuJ1BbLTjCjFRqHDU2zvKc5zgQUTo056i7TyM9gj7e0RI2gtfF+A2h71Z2MzFFQJAILAlx3TTztqRq2OEQHO2TnBpX+BKDEGhy+mNV+VT+aUHl7ik/khHMK5yyyd6PtVxjHTJBS12VKx6InvxSbT/Eat7SXmFfM9+xDopr4Fw5HV/KG+3mNQAQA+3HsZfTGlECn4tNXdBoABPqVGvfUllbR5OyM8QKlAVQtbJMnpFpFObI2Q3yeWerIeJvp4bgVSSmCdXzg233rOtOreAT2yQjURVaNePwSQtuX9PkFadfTFbfYaRIgjHnBeclE1Dm9zyyxIhHbUx/UfGvYkHxWarXhUDEhGYfhEjm4QVReonO/MYcaQeu7LEEqR0g7PmOWf4cuNfF1SWuDQBGsQU26FXgsGATJGTUoZjkwsPOtInZW0hsmHLwgs0sj6iz3JwvGDfgdv7iX+iebZCYKtBUNv0vq8s7IqY5Fk5m5Ferj+Drb0auUvlQcxotBOE3IupUwpMNLFLXju7TrLU5pjHMeM4dfeFwiXkRBdcZi/QmJEvy2kbf410I=
- python: '3.6'
- python: '3.7'
- python: '2.7'

addons:
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.PHONY: build

dependencies:
python --version
pip install -U -r build-requirements.txt
python setup.py develop

Expand Down
2 changes: 1 addition & 1 deletion build-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ pycodestyle
pyflakes
autopep8
coverage
python-coveralls
coveralls
pytest
path.py
pytest-cov
Expand Down
6 changes: 5 additions & 1 deletion formica/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
'administration_role_name': str,
'execution_role_name': str,
'main_account': bool,
'main_account_parameter': bool,
'accounts': list,
'regions': list,
'all_accounts': bool,
Expand Down Expand Up @@ -371,14 +372,17 @@ def add_stack_set_instance_retain_argument(parser):


def add_stack_set_main_account_parameter(parser):
parser.add_argument('--main-account', help='Set MainAccount Parameter', action='store_true', default=False)
parser.add_argument('--main-account-parameter', help='Set MainAccount Parameter', action='store_true',
default=False)


def add_stack_set_main_auto_regions_accounts(parser):
parser.add_argument('--all-accounts', help='Use All Accounts of this Org', action='store_true', default=False)
parser.add_argument('--all-subaccounts', help='Use Only Subaccounts of this Org',
action='store_true', default=False)
parser.add_argument('--all-regions', help='Use all Regions', action='store_true', default=False)
parser.add_argument('--excluded-regions', help='Excluded Regions from deployment', nargs='+')
parser.add_argument('--main-account', help='Deploy to Main Account only', action='store_true', default=False)


def add_stack_set_operation_preferences(parser):
Expand Down
32 changes: 22 additions & 10 deletions formica/stack_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ def validate_stack_set(args):
sys.exit(1)
else:
function(args)

return validate_stack_set


Expand All @@ -24,6 +25,7 @@ def validate_stack_set(args):
else:
logger.error('You need to set the regions and accounts you want to update.')
sys.exit(1)

return validate_stack_set


Expand Down Expand Up @@ -80,18 +82,23 @@ def accounts(args):
args = vars(args)
if (args.get('accounts')):
return [str(a) for a in args['accounts']]
elif(args['all_subaccounts']):
elif (args['all_subaccounts']):
current_account = AWS.current_session().client('sts').get_caller_identity()['Account']
return [a for a in all_accounts() if a != current_account]
elif (args['all_accounts']):
return all_accounts()
elif (args['main_account']):
return [main_account_id()]


def regions(args):
if (vars(args).get('regions')):
return vars(args)['regions']
elif(args.all_regions):
elif (args.all_regions):
return all_regions()
elif (args.excluded_regions):
excluded_regions = [r for r in all_regions() if r not in args.excluded_regions]
return excluded_regions


def all_accounts():
Expand All @@ -104,15 +111,19 @@ def all_regions():
return [r['RegionName'] for r in ec2.describe_regions()['Regions']]


def main_account_id():
sts = AWS.current_session().client('sts')
identity = sts.get_caller_identity()
return identity['Account']


def __manage_stack_set(args, create):
from .loader import Loader
client = AWS.current_session().client('cloudformation')
params = args.parameters or {}
main_account = args.main_account
main_account = args.main_account_parameter
if main_account:
sts = AWS.current_session().client('sts')
identity = sts.get_caller_identity()
params['MainAccount'] = identity['Account']
params['MainAccount'] = main_account_id()

account_regions = {}
if not create:
Expand All @@ -126,11 +137,12 @@ def __manage_stack_set(args, create):
capabilities=args.capabilities,
execution_role_name=args.execution_role_name,
administration_role_arn=args.administration_role_arn,
** account_regions)
**account_regions)

preferences = operation_preferences(args)
# Necessary for python 2.7 as it can't merge dicts with **
params.update(preferences)
if not create:
preferences = operation_preferences(args)
# Necessary for python 2.7 as it can't merge dicts with **
params.update(preferences)

loader = Loader(variables=args.vars)
loader.load()
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
],
keywords='cloudformation, aws, cloud',
packages=['formica'],
install_requires=['boto3>=1.8.0,<2.0.0', 'texttable>=1.2.0,<2.0.0', 'jinja2>=2.10,<3.0', 'pyyaml>=3.13',
install_requires=['boto3>=1.8.0,<2.0.0', 'texttable>=1.2.0,<2.0.0', 'jinja2>=2.10,<3.0', 'pyyaml==3.13',
'deepdiff==3.3.0', 'arrow>=0.12.1,<1.0.0', 'argcomplete>=1.9.4'],
entry_points={
'console_scripts': [
Expand Down
47 changes: 44 additions & 3 deletions tests/unit/test_stack_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def test_create_stack_set_with_main_account(session, client, logger, mocker):
'stack-set',
'create',
'--stack-set', STACK,
'--main-account'
'--main-account-parameter'
])

session.return_value.client.assert_called_with('sts')
Expand All @@ -120,7 +120,7 @@ def test_create_stack_set_with_main_account_and_existing_parameters(session, cli
'stack-set',
'create',
'--stack-set', STACK,
'--main-account',
'--main-account-parameter',
'--parameters', 'A=B'

])
Expand Down Expand Up @@ -180,7 +180,7 @@ def test_update_stack_set_with_main_account(session, client, logger, mocker):
'stack-set',
'update',
'--stack-set', STACK,
'--main-account'
'--main-account-parameter'
])

session.return_value.client.assert_called_with('sts')
Expand Down Expand Up @@ -349,6 +349,47 @@ def test_remove_stack_set(client, loader):
StackSetName=STACK
)

def test_excluded_regions(client, logger, loader):
client.update_stack_set.return_value = {'OperationId': '12345'}
client.list_accounts.return_value = ACCOUNTS
client.describe_regions.return_value = EC2_REGIONS
cli.main([
'stack-set',
'update',
'--stack-set', STACK,
'--all-accounts',
'--excluded-regions',
'us-west-1'
])

client.update_stack_set.assert_called_with(
StackSetName=STACK,
TemplateBody=TEMPLATE,
Accounts=['1234', '5678'],
Regions=['us-west-2']
)

def test_main_account_only_deployment(client, logger, loader):
client.update_stack_set.return_value = {'OperationId': '12345'}
client.list_accounts.return_value = ACCOUNTS
client.describe_regions.return_value = EC2_REGIONS
accountid = str(uuid4())
client.get_caller_identity.return_value = {'Account': accountid}
cli.main([
'stack-set',
'update',
'--stack-set', STACK,
'--main-account',
'--excluded-regions',
'us-west-1'
])

client.update_stack_set.assert_called_with(
StackSetName=STACK,
TemplateBody=TEMPLATE,
Accounts=[accountid],
Regions=['us-west-2']
)

def test_diff_cli_call(template, mocker, client, session):
diff = mocker.patch('formica.diff.compare_stack_set')
Expand Down

0 comments on commit 9c82e7c

Please sign in to comment.