Skip to content

Commit

Permalink
Release/0.0.34 (#34)
Browse files Browse the repository at this point in the history
You can now output values from product cloudformation stacks into ssm.
  • Loading branch information
eamonnfaherty authored May 7, 2019
1 parent 055fe4a commit 87c1f13
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 4 deletions.
55 changes: 54 additions & 1 deletion docs/source/puppet/designing_your_manifest.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ like in the example - using the parameter names like ```BucketName``` will lead
The order of precedence for parameters is account level parameters override all others and launch level parameters
override global.

#### AWS SSM Parameters
#### Retrieving AWS SSM Parameters
You can retrieve parameter values from SSM. Here is an an example:
```yaml
schema: puppet-2019-04-01
Expand All @@ -93,6 +93,59 @@ parameters:
region: eu-west-1
```

#### Setting AWS SSM Parameters
You can set the value of an SSM Parameter to the output of a CloudFormation stack output:

```yaml
account-iam-sysops:
portfolio: demo-central-it-team-portfolio
product: account-iam
version: v1
parameters:
Path:
default: /human-roles/
RoleName:
default: SysOps
deploy_to:
tags:
- regions: default_region
tag: type:prod
outputs:
ssm:
- param_name: account-iam-sysops-role-arn
stack_output: RoleArn
```

The example above will provision the product ```account-iam``` into an account. Once the stack has been completed it
will get the value of the output named ```RoleArn``` of the CloudFormation stack and insert it into SSM within the default
region using a parameter name of ```account-iam-sysops-role-arn```

You can also set override which region the output is read from and which region the SSM parameter is written to:

```yaml
account-iam-sysops:
portfolio: demo-central-it-team-portfolio
product: account-iam
version: v1
parameters:
Path:
default: /human-roles/
RoleName:
default: SysOps
deploy_to:
tags:
- regions: default_region
tag: type:prod
outputs:
ssm:
- param_name: account-iam-sysops-role-arn
stack_output: RoleArn
region: us-east-1
```

There is currently no capability of reading a value from a CloudFormation stack from one region and setting an SSM param
in another.

#### Macros
You can also use a macro to set the value of a parameter. It works in the same way as a normal parameter except it
executes a function to get the value first. Here is an an example:
Expand Down
58 changes: 56 additions & 2 deletions servicecatalog_puppet/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,6 @@ def deploy_launch_to_account_and_region(
):
launch_name = launch.get('launch_name')
stack_name = "-".join([PREFIX, account, region, launch_name])

logger.info('Creating plan, params: {}'.format(params))
response = service_catalog.create_provisioned_product_plan(
PlanName=stack_name,
Expand Down Expand Up @@ -380,12 +379,67 @@ def deploy_launch_to_account_and_region(
response = service_catalog.describe_provisioned_product_plan(
PlanId=plan_id
)
logger.info("plan_id is: {}".format(plan_id))
execute_status = response.get('ProvisionedProductPlanDetails').get('Status')
logger.info('Waiting for execute: {}'.format(execute_status))
time.sleep(5)

if execute_status == 'CREATE_SUCCESS':
logger.info("Product provisioned")
if launch.get('outputs', {}).get('ssm') is not None:
logger.info("There are ssm outputs that need processing")
provision_product_id = response.get('ProvisionedProductPlanDetails').get('ProvisionProductId')
stack_name = "SC-{}-{}".format(account, provision_product_id)
logger.info("Need to wait for stack completion for outputs to become available")
role = "arn:aws:iam::{}:role/{}".format(account, 'servicecatalog-puppet/PuppetRole')
with betterboto_client.CrossAccountClientContextManager(
'cloudformation', role, 'xross', region_name=region
) as cloudformation:
waiter = cloudformation.get_waiter('stack_create_complete')
waiter.wait(StackName=stack_name)
logger.info("Stack is now completed, continuing")

for outputs in launch.get('outputs', {}).get('ssm', []):
ssm_param_name = outputs.get('param_name')
ssm_param_value = outputs.get('stack_output')
ssm_param_region = outputs.get('region', HOME_REGION)
logger.info('Trying to set SSM parameter: {}'.format(ssm_param_name))
logger.info(('Looking for stack: {}'.format(stack_name)))
stack_response = cloudformation.describe_stacks(
StackName=stack_name
)
if len(stack_response.get('Stacks')) != 1:
raise Exception("Found more or less than 1 stack with the name: {}".format(
stack_name
))
stack = stack_response.get('Stacks')[0]
logger.info(('Looking for output: {} in: {}'.format(ssm_param_value, stack.get('Outputs', []))))
for stack_output in stack.get('Outputs', []):
if stack_output.get('OutputKey') == ssm_param_value:
logger.info('Adding SSM parameter: {} of value: {} in region: {}'.format(
ssm_param_name, stack_output.get('OutputValue'), ssm_param_region
))
with betterboto_client.ClientContextManager('ssm', region_name=ssm_param_region) as ssm:
ssm.put_parameter(
Name=ssm_param_name,
Value=stack_output.get('OutputValue'),
Description=stack_output.get('Description', ''),
Type='String',
Tags=[
{
"Key": "SourceStackName",
"Value": stack_name,
},
{
"Key": "SourceStackOutputName",
"Value": ssm_param_value,
},
{
"Key": "SourceStackId",
"Value": stack.get('StackId'),
},
]
)
logger.info("Product provisioned")
else:
raise Exception("Execute was not successful: {}".format(execute_status))
service_catalog.delete_provisioned_product_plan(PlanId=plan_id)
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

setuptools.setup(
name="aws-service-catalog-puppet",
version="0.0.33",
version="0.0.34",
author="Eamonn Faherty",
author_email="[email protected]",
description="Making it easier to deploy ServiceCatalog products",
Expand Down

0 comments on commit 87c1f13

Please sign in to comment.