Ejemplo n.º 1
0
class TestPreprocessor(TestCase):
    def setUp(self):
        # c can override b, which can override a
        data_sources = ['yaml:c:datasources/nested.yaml',
                        'yaml:datasources/b.yaml',
                        'yaml:datasources/a.yaml']

        self.datasource_collection = DataSourceCollection(data_sources)
        self.preprocessor = Preprocessor(self.datasource_collection, 'us-east-1')

    def test_instance_chooser(self):
        with open('preprocessor/instance_chooser1.yaml') as instance_chooser1, \
                open('preprocessor/instance_chooser2.yaml') as instance_chooser2, \
                open('preprocessor/instance_chooser3.yaml') as instance_chooser3:
            template = RainbowYamlLoader(instance_chooser1).get_data()
            template2 = RainbowYamlLoader(instance_chooser2).get_data()
            template3 = RainbowYamlLoader(instance_chooser3).get_data()

        processed = self.preprocessor.process(template)
        self.assertEqual(processed['Resources']['Properties']['InstanceType'], 'c1.xlarge')

        processed2 = self.preprocessor.process(template2)
        self.assertEqual(processed2['Resources']['Properties']['InstanceType'], 'c3.large')

        self.assertRaises(InvalidInstanceException, self.preprocessor.process, template3)

    def test_invalid_function(self):
        self.assertRaises(InvalidPreprocessorFunctionException, self.preprocessor.process, {'Rb::NoSuchFunction': ''})
Ejemplo n.º 2
0
class TestPreprocessor(TestCase):
    def setUp(self):
        # c can override b, which can override a
        data_sources = ['yaml:c:datasources/nested.yaml',
                        'yaml:datasources/b.yaml',
                        'yaml:datasources/a.yaml']

        self.datasource_collection = DataSourceCollection(data_sources)
        self.preprocessor = Preprocessor(self.datasource_collection, 'us-east-1')

    def test_instance_chooser(self):
        with open('preprocessor/instance_chooser1.yaml') as instance_chooser1, \
                open('preprocessor/instance_chooser2.yaml') as instance_chooser2, \
                open('preprocessor/instance_chooser3.yaml') as instance_chooser3, \
                open('preprocessor/instance_chooser4.yaml') as instance_chooser4:
            template = RainbowYamlLoader(instance_chooser1).get_data()
            template2 = RainbowYamlLoader(instance_chooser2).get_data()
            template3 = RainbowYamlLoader(instance_chooser3).get_data()
            template4 = RainbowYamlLoader(instance_chooser4).get_data()

        processed = self.preprocessor.process(template)
        self.assertEqual(processed['Resources']['Properties']['InstanceType'], 'c1.xlarge')

        processed2 = self.preprocessor.process(template2)
        self.assertEqual(processed2['Resources']['Properties']['InstanceType'], 'c3.large')

        self.assertRaises(InvalidInstanceException, self.preprocessor.process, template3)

        processed4 = self.preprocessor.process(template4)
        self.assertEqual(processed4['Resources']['Properties']['InstanceType'], 'c3.large')

    def test_invalid_function(self):
        self.assertRaises(InvalidPreprocessorFunctionException, self.preprocessor.process, {'Rb::NoSuchFunction': ''})
Ejemplo n.º 3
0
    def setUp(self):
        # c can override b, which can override a
        data_sources = ['yaml:c:datasources/nested.yaml',
                        'yaml:datasources/b.yaml',
                        'yaml:datasources/a.yaml']

        self.datasource_collection = DataSourceCollection(data_sources)
        self.preprocessor = Preprocessor(self.datasource_collection, 'us-east-1')
Ejemplo n.º 4
0
    def setUp(self):
        # c can override b, which can override a
        data_sources = ['yaml:c:datasources/nested.yaml',
                        'yaml:datasources/b.yaml',
                        'yaml:datasources/a.yaml']

        self.datasource_collection = DataSourceCollection(data_sources)
        self.preprocessor = Preprocessor(self.datasource_collection, 'us-east-1')
Ejemplo n.º 5
0
def main():  # pragma: no cover
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger('rainbow')

    parser = argparse.ArgumentParser(description='Load cloudformation templates with cool data sources as arguments')
    parser.add_argument('-d', '--data-source', metavar='DATASOURCE', dest='datasources', action='append', default=[],
                        help='Data source. Format is data_sourcetype:data_sourceargument. For example, ' +
                             'cfn_outputs:[region:]stackname, cfn_resources:[region:]stackname, or ' +
                             'yaml:yamlfile. First match is used')
    parser.add_argument('-r', '--region', default='us-east-1', help='AWS region')
    parser.add_argument('-n', '--noop', action='store_true',
                        help="Don't actually call aws; just show what would be done.")
    parser.add_argument('-v', '--verbose', action='store_true')
    parser.add_argument('--dump-datasources', action='store_true',
                        help='Simply output all datasources and their values')
    parser.add_argument('--update-stack', action='store_true',
                        help='Update a pre-existing stack rather than create a new one')
    parser.add_argument('--block', action='store_true',
                        help='Track stack creation, if the stack creation failed, exits with a non-zero exit code')

    parser.add_argument('-b', '--bucket', help='The bucket to store Cloudformation template within S3.')
    parser.add_argument('-f', '--filename', help='The filename to store the Cloudformation template as within S3.')
    parser.add_argument('-t', '--timeout', help='The timeout for s3 communication.')

    parser.add_argument('stack_name')
    parser.add_argument('templates', metavar='template', type=str, nargs='+')

    args = parser.parse_args()
    if args.verbose:
        logger.setLevel(logging.DEBUG)

    Cloudformation.default_region = args.region
    datasource_collection = DataSourceCollection(args.datasources, args.bucket)

    # load and merge templates
    template = TemplateLoader.load_templates(args.templates)

    # preprocess computed values
    preprocessor = Preprocessor(datasource_collection=datasource_collection, region=args.region)
    template = preprocessor.process(template)

    # build list of parameters for stack creation/update from datasources
    parameters = Cloudformation.resolve_template_parameters(template, datasource_collection)

    if args.dump_datasources:
        pprint.pprint(datasource_collection)
        return

    logger.debug('Will create stack "%s" with parameters: %r', args.stack_name, parameters)
    logger.debug('Template:\n%s', yaml.dump(template))

    if args.noop:
        logger.info('NOOP mode. exiting')
        return

    cloudformation = Cloudformation(args.region)

    if args.block:
        # set the iterator prior to updating the stack, so it'll begin from the current bottom
        stack_events_iterator = cloudformation.tail_stack_events(args.stack_name, None if args.update_stack else 0)

    if args.update_stack:
        cloudformation.update_stack(args.stack_name, template, parameters, args.bucket, args.filename, args.timeout)
    else:
        cloudformation.create_stack(args.stack_name, template, parameters, args.bucket, args.filename, args.timeout)

    if args.block:
        for event in stack_events_iterator:
            if isinstance(event, StackFailStatus):
                logger.warn('Stack creation failed: %s', event)
                sys.exit(1)
            elif isinstance(event, StackSuccessStatus):
                logger.info('Stack creation succeeded: %s', event)
            else:
                logger.info('%(resource_type)s %(logical_resource_id)s %(physical_resource_id)s %(resource_status)s '
                            '%(resource_status_reason)s', event)
Ejemplo n.º 6
0
def main():  # pragma: no cover
    logging.basicConfig(level=logging.INFO)

    # boto logs errors in addition to throwing exceptions. on rainbow.cloudformation.Cloudformation.update_stack()
    # I'm ignoring the 'No updates are to be performed.' exception, so I don't want it to be logged.
    logging.getLogger("boto").setLevel(logging.CRITICAL)

    logger = logging.getLogger("rainbow")

    parser = argparse.ArgumentParser(description="Load cloudformation templates with cool data sources as arguments")
    parser.add_argument(
        "-d",
        "--data-source",
        metavar="DATASOURCE",
        dest="datasources",
        action="append",
        default=[],
        help="Data source. Format is data_sourcetype:data_sourceargument. For example, "
        + "cfn_outputs:[region:]stackname, cfn_resources:[region:]stackname, or "
        + "yaml:yamlfile. First match is used",
    )
    parser.add_argument("-r", "--region", default="us-east-1", help="AWS region")
    parser.add_argument(
        "-n", "--noop", action="store_true", help="Don't actually call aws; just show what would be done."
    )
    parser.add_argument("-v", "--verbose", action="store_true")
    parser.add_argument(
        "--dump-datasources", action="store_true", help="Simply output all datasources and their values"
    )
    parser.add_argument(
        "--update-stack", action="store_true", help="Update a pre-existing stack rather than create a new one"
    )
    parser.add_argument(
        "--update-stack-if-exists",
        action="store_true",
        help="Create a new stack if it doesn't exist, update if it does",
    )
    parser.add_argument(
        "--block",
        action="store_true",
        help="Track stack creation, if the stack creation failed, exits with a non-zero exit code",
    )

    parser.add_argument("stack_name")
    parser.add_argument("templates", metavar="template", type=str, nargs="+")

    args = parser.parse_args()
    if args.verbose:
        logger.setLevel(logging.DEBUG)

    Cloudformation.default_region = args.region
    datasource_collection = DataSourceCollection(args.datasources)

    # load and merge templates
    template = TemplateLoader.load_templates(args.templates)

    # preprocess computed values
    preprocessor = Preprocessor(datasource_collection=datasource_collection, region=args.region)
    template = preprocessor.process(template)

    # build list of parameters for stack creation/update from datasources
    parameters = Cloudformation.resolve_template_parameters(template, datasource_collection)

    if args.dump_datasources:
        pprint.pprint(datasource_collection)
        return

    logger.debug('Will create stack "%s" with parameters: %r', args.stack_name, parameters)
    logger.debug("Template:\n%s", yaml.dump(template))

    if args.noop:
        logger.info("NOOP mode. exiting")
        return

    cloudformation = Cloudformation(args.region)

    if args.update_stack_if_exists:
        if cloudformation.stack_exists(args.stack_name):
            args.update_stack = True
        else:
            args.update_stack = False

    if args.block:
        # set the iterator prior to updating the stack, so it'll begin from the current bottom
        stack_events_iterator = cloudformation.tail_stack_events(args.stack_name, None if args.update_stack else 0)

    if args.update_stack:
        stack_modified = cloudformation.update_stack(args.stack_name, template, parameters)
        if not stack_modified:
            logger.info("No updates to be performed")
    else:
        cloudformation.create_stack(args.stack_name, template, parameters)
        stack_modified = True

    if args.block and stack_modified:
        for event in stack_events_iterator:
            if isinstance(event, StackFailStatus):
                logger.warn("Stack creation failed: %s", event)
                sys.exit(1)
            elif isinstance(event, StackSuccessStatus):
                logger.info("Stack creation succeeded: %s", event)
            else:
                logger.info(
                    "%(resource_type)s %(logical_resource_id)s %(physical_resource_id)s %(resource_status)s "
                    "%(resource_status_reason)s",
                    event,
                )
Ejemplo n.º 7
0
def main():  # pragma: no cover
    logging.basicConfig(level=logging.INFO)

    # boto logs errors in addition to throwing exceptions. on rainbow.cloudformation.Cloudformation.update_stack()
    # I'm ignoring the 'No updates are to be performed.' exception, so I don't want it to be logged.
    logging.getLogger('boto').setLevel(logging.CRITICAL)

    logger = logging.getLogger('rainbow')

    parser = argparse.ArgumentParser(description='Load cloudformation templates with cool data sources as arguments')
    parser.add_argument('-d', '--data-source', metavar='DATASOURCE', dest='datasources', action='append', default=[],
                        help='Data source. Format is data_sourcetype:data_sourceargument. For example, ' +
                             'cfn_outputs:[region:]stackname, cfn_resources:[region:]stackname, or ' +
                             'yaml:yamlfile. First match is used')
    parser.add_argument('-r', '--region', default='us-east-1', help='AWS region')
    parser.add_argument('-n', '--noop', action='store_true',
                        help="Don't actually call aws; just show what would be done.")
    parser.add_argument('-v', '--verbose', action='store_true')
    parser.add_argument('--dump-datasources', action='store_true',
                        help='Simply output all datasources and their values')
    parser.add_argument('--update-stack', action='store_true',
                        help='Update a pre-existing stack rather than create a new one')
    parser.add_argument('--update-stack-if-exists', action='store_true',
                        help='Create a new stack if it doesn\'t exist, update if it does')
    parser.add_argument('--block', action='store_true',
                        help='Track stack creation, if the stack creation failed, exits with a non-zero exit code')

    parser.add_argument('stack_name')
    parser.add_argument('templates', metavar='template', type=str, nargs='+')

    args = parser.parse_args()
    if args.verbose:
        logger.setLevel(logging.DEBUG)

    Cloudformation.default_region = args.region
    datasource_collection = DataSourceCollection(args.datasources)

    # load and merge templates
    template = TemplateLoader.load_templates(args.templates)

    # preprocess computed values
    preprocessor = Preprocessor(datasource_collection=datasource_collection, region=args.region)
    template = preprocessor.process(template)

    # build list of parameters for stack creation/update from datasources
    parameters = Cloudformation.resolve_template_parameters(template, datasource_collection)

    if args.dump_datasources:
        pprint.pprint(datasource_collection)
        return

    logger.debug('Will create stack "%s" with parameters: %r', args.stack_name, parameters)
    logger.debug('Template:\n%s', yaml.dump(template))

    if args.noop:
        logger.info('NOOP mode. exiting')
        return

    cloudformation = Cloudformation(args.region)

    if args.update_stack_if_exists:
        if cloudformation.stack_exists(args.stack_name):
            args.update_stack = True
        else:
            args.update_stack = False

    if args.block:
        # set the iterator prior to updating the stack, so it'll begin from the current bottom
        stack_events_iterator = cloudformation.tail_stack_events(args.stack_name, None if args.update_stack else 0)

    if args.update_stack:
        stack_modified = cloudformation.update_stack(args.stack_name, template, parameters)
        if not stack_modified:
            logger.info('No updates to be performed')
    else:
        cloudformation.create_stack(args.stack_name, template, parameters)
        stack_modified = True

    if args.block and stack_modified:
        for event in stack_events_iterator:
            if isinstance(event, StackFailStatus):
                logger.warn('Stack creation failed: %s', event)
                sys.exit(1)
            elif isinstance(event, StackSuccessStatus):
                logger.info('Stack creation succeeded: %s', event)
            else:
                logger.info('%(resource_type)s %(logical_resource_id)s %(physical_resource_id)s %(resource_status)s '
                            '%(resource_status_reason)s', event)
Ejemplo n.º 8
0
def main():  # pragma: no cover
    logging.basicConfig(level=logging.INFO)

    # boto logs errors in addition to throwing exceptions. on rainbow.cloudformation.Cloudformation.update_stack()
    # I'm ignoring the 'No updates are to be performed.' exception, so I don't want it to be logged.
    logging.getLogger('boto').setLevel(logging.CRITICAL)

    logger = logging.getLogger('rainbow')

    parser = argparse.ArgumentParser(description='Load cloudformation templates with cool data sources as arguments')
    parser.add_argument('-d', '--data-source', metavar='DATASOURCE', dest='datasources', action='append', default=[],
                        help='Data source. Format is data_sourcetype:data_sourceargument. For example, ' +
                             'cfn_outputs:[region:]stackname, cfn_resources:[region:]stackname, or ' +
                             'yaml:yamlfile. First match is used')
    parser.add_argument('-t', '--tag', metavar='TAG', dest='tags', action='append', default=[],
                        help='Tag. Format is key=value. Multiple tags can be provided, one per -t')
    parser.add_argument('-r', '--region', default='us-east-1', help='AWS region')
    parser.add_argument('-n', '--noop', action='store_true',
                        help="Don't actually call aws; just show what would be done.")
    parser.add_argument('-v', '--verbose', action='store_true')
    parser.add_argument('--dump-datasources', action='store_true',
                        help='Simply output all datasources and their values')
    parser.add_argument('--update-stack', action='store_true',
                        help='Update a pre-existing stack rather than create a new one')
    parser.add_argument('--update-stack-if-exists', action='store_true',
                        help='Create a new stack if it doesn\'t exist, update if it does')
    parser.add_argument('--block', action='store_true',
                        help='Track stack creation, if the stack creation failed, exits with a non-zero exit code')

    parser.add_argument('stack_name')
    parser.add_argument('templates', metavar='template', type=str, nargs='+')

    args = parser.parse_args()
    if args.verbose:
        logger.setLevel(logging.DEBUG)

    Cloudformation.default_region = args.region
    datasource_collection = DataSourceCollection(args.datasources)
    tags = dict([ item.split('=') for item in args.tags ])

    # load and merge templates
    template = TemplateLoader.load_templates(args.templates)

    # preprocess computed values
    preprocessor = Preprocessor(datasource_collection=datasource_collection, region=args.region)
    template = preprocessor.process(template)

    # build list of parameters for stack creation/update from datasources
    parameters = Cloudformation.resolve_template_parameters(template, datasource_collection)

    if args.dump_datasources:
        pprint.pprint(datasource_collection)
        return

    logger.debug('Will create stack "%s" with parameters: %r', args.stack_name, parameters)
    logger.debug('Template:\n%s', yaml.dump(template))

    if args.noop:
        logger.info('NOOP mode. exiting')
        return

    cloudformation = Cloudformation(args.region)

    if args.update_stack_if_exists:
        if cloudformation.stack_exists(args.stack_name):
            args.update_stack = True
        else:
            args.update_stack = False

    if args.block:
        # set the iterator prior to updating the stack, so it'll begin from the current bottom
        stack_events_iterator = cloudformation.tail_stack_events(args.stack_name, None if args.update_stack else 0)

    if args.update_stack:
        stack_modified = cloudformation.update_stack(args.stack_name, template, parameters, tags)
        if not stack_modified:
            logger.info('No updates to be performed')
    else:
        cloudformation.create_stack(args.stack_name, template, parameters, tags)
        stack_modified = True

    if args.block and stack_modified:
        for event in stack_events_iterator:
            if isinstance(event, StackFailStatus):
                logger.warn('Stack creation failed: %s', event)
                sys.exit(1)
            elif isinstance(event, StackSuccessStatus):
                logger.info('Stack creation succeeded: %s', event)
            else:
                logger.info('%(resource_type)s %(logical_resource_id)s %(physical_resource_id)s %(resource_status)s '
                            '%(resource_status_reason)s', event)