cloudtools / troposphere

troposphere - Python library to create AWS CloudFormation descriptions
BSD 2-Clause "Simplified" License
4.93k stars 1.45k forks source link

Configsets support #424

Open lony opened 8 years ago

lony commented 8 years ago

When I use the following method http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-init.html#aws-resource-init-configsets

I get ValueError('config property is required') as a workaround I change one of my changesets to config, but is there better way to "validate" Metadata?

phobologic commented 8 years ago

Can you give a snippet of the code that you're using that isn't working the way you expect?

lony commented 8 years ago
import boto3

import troposphere
import troposphere.ec2 as ec2
from troposphere.autoscaling import Metadata
from troposphere.cloudformation import Init, InitFile, InitFiles, InitConfig
from troposphere.iam import InstanceProfile

template = troposphere.Template()
template.add_version("2010-09-09")

param_type = template.add_parameter(troposphere.Parameter(
        'InstanceType',
        Description='Type of EC2 instance',
        Type='String',
))
param_key = template.add_parameter(troposphere.Parameter(
        'KeyName',
        Description='Name of an existing EC2 KeyPair to enable SSH access to the instance',
        Type='String',
))
param_ami = template.add_parameter(troposphere.Parameter(
        'AMI',
        Description='Machine image to use (AMI)',
        Type='String',
))

instance_ec2 = template.add_resource(ec2.Instance(
        "Foo",
        InstanceType=troposphere.Ref(param_type),
        ImageId=troposphere.Ref(param_ami),
        Metadata=Metadata(
                # Usage
                # http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-init.html
                Init({
                    "configSets": {
                        "ascending": ["config1", "config2"]
                    },
                    '**config1**': InitConfig(
                            files=InitFiles({
                                '/var/lib/jenkins/.ssh/config': InitFile(
                                        content=troposphere.Join('\n', [
                                            "# TBD"
                                        ]),
                                        mode='000600',
                                        owner='jenkins',
                                        group='jenkins'),
                                '/var/lib/jenkins/.ssh/jenkins_deploy': InitFile(
                                        content=troposphere.Join('\n', [
                                            "# TBD"
                                        ]),
                                        mode='000600',
                                        owner='jenkins',
                                        group='jenkins'),
                            }),
                    ),
                    'config2': InitConfig(
                            files=InitFiles({
                                '/etc/httpd/conf.d/jenkins-vhost-apache.conf': InitFile(
                                        content=troposphere.Join('\n', [
                                            "# TBD"
                                        ]),
                                        mode='000644',
                                        owner='root',
                                        group='root'),
                            }),
                    )
                })
        ),
        UserData=troposphere.Base64(
                # Install Jenkins
                # https://wiki.jenkins-ci.org/display/JENKINS/Installing+Jenkins+on+Red+Hat+distributions
                troposphere.Join(
                        "\n",
                        [
                            "# AWS init",
                            troposphere.Join("", [
                                "/opt/aws/bin/cfn-init ",
                                " -s ", {"Ref": "AWS::StackName"},
                                " -r Foo ",
                                " --region ", {"Ref": "AWS::Region"},
                                " -c ascending",
                            ]),
                        ]
                )
        ),
))

print(template.to_json())

Results in:

Traceback (most recent call last):
  File "pp.py", line 65, in <module>
    group='root'),
  File "/Users/lony/Desktop/data-platform/src/operations/jenkins/venv/lib/python2.7/site-packages/troposphere/cloudformation.py", line 187, in __init__
    self.validate(data, dict(kwargs))
  File "/Users/lony/Desktop/data-platform/src/operations/jenkins/venv/lib/python2.7/site-packages/troposphere/cloudformation.py", line 207, in validate
    raise ValueError('config property is required')
ValueError: config property is required

Just because I don't name one configset "config". Even if it is valid by AWS.

ksinghttam commented 8 years ago

This is months later but the solution is to write it as:

`Metadata=Metadata(

Usage

            # http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-init.html
            Init(
                    InitConfigSets(configSets=
                        {"ascending": ["config1", "config2"]}
                ),
                'config1': InitConfig(
                        files=InitFiles({

etc; `

It's mildly inconsistent with the general troposphere API....

kpx-dev commented 7 years ago

I was having the same issue, I used this and it seems to work for me:

Metadata=Metadata(Init(
        InitConfigSets(InstallAndConfigure=['config']),
        config=InitConfig(
            commands={
                '01_setup_aws': {
                    'command': Join('', [
                        'aws configure set s3.signature_version s3v4\n',
                        'aws configure set region ', Ref("AWS::Region")
                    ])
                }
            }
        ),
    ))
noelmccrory commented 6 years ago

A similar issue occurs when you try to use the TemplateGenerator to read an existing CFT that contains a AWS::CloudFormation::Init section with no "config" property, even though it has a "configSets" property. See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-init.html