예제 #1
0
    def test_create(self):
        with settings(abort_on_prompts=True):
            project = 'dummy1'
            stackname = '%s--%s' % (project, self.environment)

            cfn.ensure_destroyed(stackname)
            self.stacknames.append(stackname)

            cfngen.generate_stack(project, stackname=stackname)
            bootstrap.create_stack(stackname)

            buildvars.switch_revision(stackname, 'master')
            buildvars.force(stackname, 'answer', 'forty-two')

            cfn.cmd(stackname, "ls -l /", username=BOOTSTRAP_USER, concurrency='parallel')
            cfn.cmd(stackname, "ls -l /", username=BOOTSTRAP_USER, concurrency='parallel', node=1)

            cfn.download_file(stackname, "/bin/ls", "ls", use_bootstrap_user="******")
            self.assertTrue(os.path.isfile("./ls"))

            cfn.download_file(stackname, "/bin/less", "venv/bin/", use_bootstrap_user="******")
            self.assertTrue(os.path.isfile("./venv/bin/less"))

            cfn.download_file(stackname, "/bin/pwd", "subfolder/pwd", use_bootstrap_user="******")
            self.assertTrue(os.path.isfile("./subfolder/pwd"))

            lifecycle.stop_if_running_for(stackname, minimum_minutes=60 * 24 * 365) # should exercise the code but do nothing, as this test's instance can't have been running for a year
예제 #2
0
파일: cfn.py 프로젝트: stephenwf/builder
def generate_stack_from_input(pname, instance_id=None):
    """creates a new CloudFormation file for the given project."""
    if not instance_id:
        default_instance_id = core_utils.ymd()
        instance_id = utils.uin("instance id", default_instance_id)
    stackname = core.mk_stackname(pname, instance_id)
    more_context = {'stackname': stackname}

    # prompt user for alternate configurations
    pdata = project.project_data(pname)
    if 'aws-alt' in pdata:

        def helpfn(altkey):
            try:
                return pdata['aws-alt'][altkey]['description']
            except KeyError:
                return None

        default = 'skip this step'
        alt_config = [default] + pdata['aws-alt'].keys()
        alt_config = utils._pick('alternative config',
                                 alt_config,
                                 helpfn=helpfn)
        if alt_config != default:
            more_context['alt-config'] = alt_config
    cfngen.generate_stack(pname, **more_context)
    return stackname
예제 #3
0
    def test_blue_green_operations(self):
        with settings(abort_on_prompts=True):
            project = 'project-with-cluster-integration-tests'
            stackname = '%s--%s' % (project, self.environment)

            cfn.ensure_destroyed(stackname)
            self.stacknames.append(stackname)
            cfngen.generate_stack(project, stackname=stackname)
            bootstrap.create_stack(stackname)

            output = cfn.cmd(stackname,
                             'ls -l /',
                             username=BOOTSTRAP_USER,
                             concurrency='blue-green')
            print output
예제 #4
0
    def test_create(self):
        with settings(abort_on_prompts=True):
            project = 'dummy1'
            stackname = '%s--%s' % (project, self.environment)

            cfn.ensure_destroyed(stackname)
            self.stacknames.append(stackname) # ensures stack is destroyed

            cfngen.generate_stack(project, stackname=stackname)
            bootstrap.create_stack(stackname)

            buildvars.switch_revision(stackname, 'master')
            buildvars.force(stackname, 'answer', 'forty-two')

            lifecycle.stop(stackname)
            lifecycle.start(stackname)
예제 #5
0
def generate_stack_from_input(pname, instance_id=None, alt_config=None):
    """creates a new CloudFormation/Terraform file for the given project `pname` with
    the identifier `instance_id` using the (optional) project configuration `alt_config`."""
    more_context = check_user_input(pname, instance_id, alt_config)
    stackname = more_context['stackname']

    # ~TODO: return the templates used here, so that they can be passed down to~
    # ~bootstrap.create_stack() without relying on them implicitly existing~
    # ~on the filesystem~
    # lsh@2021-07: having the files on the filesystem with predictable names seems more
    # robust than carrying it around as a parameter through complex logic.
    _, cloudformation_file, terraform_file = cfngen.generate_stack(
        pname, **more_context)

    if cloudformation_file:
        print('cloudformation template:')
        print(json.dumps(json.load(open(cloudformation_file, 'r')), indent=4))
        print()

    if terraform_file:
        print('terraform template:')
        print(json.dumps(json.load(open(terraform_file, 'r')), indent=4))
        print()

    if cloudformation_file:
        LOG.info('wrote: %s' % os.path.abspath(cloudformation_file))

    if terraform_file:
        LOG.info('wrote: %s' % os.path.abspath(terraform_file))

    # see: `buildercore.config.BUILDER_NON_INTERACTIVE` for skipping confirmation prompts
    utils.confirm('the above resources will be created')

    return stackname
예제 #6
0
def generate_stack_from_input(pname, instance_id=None, alt_config=None):
    """creates a new CloudFormation file for the given project."""
    instance_id = instance_id or utils.uin("instance id", core_utils.ymd())
    stackname = core.mk_stackname(pname, instance_id)
    checks.ensure_stack_does_not_exist(stackname)
    more_context = {'stackname': stackname}

    pdata = project.project_data(pname)
    if alt_config:
        ensure(
            'aws-alt' in pdata,
            "alternative configuration name given, but project has no alternate configurations"
        )

    # prompt user for alternate configurations
    if pdata['aws-alt']:
        default = 'skip'

        def helpfn(altkey):
            if altkey == default:
                return 'uses the default configuration'
            try:
                return pdata['aws-alt'][altkey]['description']
            except KeyError:
                return None

        if instance_id in pdata['aws-alt'].keys():
            LOG.info(
                "instance-id found in known alternative configurations. using configuration %r",
                instance_id)
            more_context['alt-config'] = instance_id
        else:
            alt_config_choices = [default] + list(pdata['aws-alt'].keys())
            if not alt_config:
                alt_config = utils._pick('alternative config',
                                         alt_config_choices,
                                         helpfn=helpfn)
            if alt_config != default:
                more_context['alt-config'] = alt_config

    # TODO: return the templates used here, so that they can be passed down to
    # bootstrap.create_stack() without relying on them implicitly existing
    # on the filesystem
    cfngen.generate_stack(pname, **more_context)
    return stackname
예제 #7
0
    def test_create(self):
        with settings(abort_on_prompts=True):
            project = 'dummy1'
            stackname = '%s--%s' % (project, self.environment)

            cfn.ensure_destroyed(stackname)
            self.stacknames.append(stackname)

            cfngen.generate_stack(project, stackname=stackname)
            bootstrap.create_stack(stackname)

            buildvars.switch_revision(stackname, 'master')
            buildvars.force(stackname, 'answer', 'forty-two')

            cfn.cmd(stackname,
                    "ls -l /",
                    username=BOOTSTRAP_USER,
                    concurrency='parallel')
            cfn.cmd(stackname,
                    "ls -l /",
                    username=BOOTSTRAP_USER,
                    concurrency='parallel',
                    node=1)

            cfn.download_file(stackname,
                              "/bin/ls",
                              "ls",
                              use_bootstrap_user="******")
            self.assertTrue(os.path.isfile("./ls"))

            cfn.download_file(stackname,
                              "/bin/less",
                              "venv/bin/",
                              use_bootstrap_user="******")
            self.assertTrue(os.path.isfile("./venv/bin/less"))

            cfn.download_file(stackname,
                              "/bin/pwd",
                              "subfolder/pwd",
                              use_bootstrap_user="******")
            self.assertTrue(os.path.isfile("./subfolder/pwd"))

            lifecycle.stop_if_running_for(
                stackname, minimum_minutes=60 * 24 * 365
            )  # should exercise the code but do nothing, as this test's instance can't have been running for a year
예제 #8
0
def deploy(pname, instance_id=None, branch='master', part_filter=None):
    pdata = project.project_data(pname)
    if not branch:
        branch_list = utils.git_remote_branches(pdata['repo'])
        branch_list = impose_ordering(branch_list)
        branch = utils._pick('branch', branch_list, deffile('.branch'))
    stackname = cfn.generate_stack_from_input(pname, instance_id)

    region = pdata['aws']['region']
    active_stacks = core.active_stack_names(region)
    if stackname in active_stacks:
        LOG.info("stack %r exists, skipping creation", stackname)
    else:
        LOG.info("stack %r doesn't exist, creating", stackname)
        more_context = cfngen.choose_config(stackname)
        more_context['branch'] = branch
        cfngen.generate_stack(pname, **more_context)

    bootstrap.create_update(stackname, part_filter)
    setdefault('.active-stack', stackname)
예제 #9
0
    def test_create(self):
        with settings(abort_on_prompts=True):
            project = 'dummy1'
            stackname = '%s--%s' % (project, self.environment)

            cfn.ensure_destroyed(stackname)
            self.stacknames.append(stackname)

            cfngen.generate_stack(project, stackname=stackname)
            bootstrap.create_stack(stackname)

            buildvars.switch_revision(stackname, 'master')
            buildvars.force(stackname, 'answer', 'forty-two')

            lifecycle.stop(stackname)
            lifecycle.start(stackname)

            cfn.cmd(stackname,
                    "ls -l /",
                    username=BOOTSTRAP_USER,
                    concurrency='parallel')

            cfn.download_file(stackname,
                              "/bin/ls",
                              "ls",
                              use_bootstrap_user="******")
            self.assertTrue(os.path.isfile("./ls"))

            cfn.download_file(stackname,
                              "/bin/less",
                              "venv/bin/",
                              use_bootstrap_user="******")
            self.assertTrue(os.path.isfile("./venv/bin/less"))

            cfn.download_file(stackname,
                              "/bin/pwd",
                              "subfolder/pwd",
                              use_bootstrap_user="******")
            self.assertTrue(os.path.isfile("./subfolder/pwd"))
예제 #10
0
def create_stack(pname):
    """creates a new CloudFormation template for the given project."""
    default_instance_id = core_utils.ymd()
    inst_id = utils.uin("instance id", default_instance_id)
    stackname = core.mk_stackname(pname, inst_id)
    more_context = {'instance_id': stackname}

    # prompt user for alternate configurations
    pdata = project.project_data(pname)
    if pdata.has_key('aws-alt'):
        def helpfn(altkey):
            try:
                return pdata['aws-alt'][altkey]['description']
            except KeyError:
                return None
        default = 'skip this step'
        alt_config = [default] + pdata['aws-alt'].keys()
        alt_config = utils._pick('alternative config', alt_config, helpfn=helpfn)
        if alt_config != default:
            more_context['alt-config'] = alt_config
    cfngen.generate_stack(pname, **more_context)
    return stackname
예제 #11
0
    def set_up_stack(cls, project, explicitly_start=False):
        switch_in_test_settings()

        # to re-use an existing stack, ensure cls.reuse_existing_stack is True
        # this will read the instance name from a temporary file (if it exists) and
        # look for that, creating it if doesn't exist yet
        # also ensure cls.cleanup is False so the instance isn't destroyed after tests complete
        cls.reuse_existing_stack = config.TWI_REUSE_STACK
        cls.cleanup = config.TWI_CLEANUP

        cls.stacknames = []
        cls.environment = generate_environment_name()
        # cls.temp_dir, cls.rm_temp_dir = utils.tempdir()

        # debugging only, where we keep an instance up between processes
        cls.state, cls.statefile = {}, '/tmp/.open-test-instances.txt'

        if cls.reuse_existing_stack and os.path.exists(cls.statefile):
            # evidence of a previous instance and we've been told to re-use old instances
            old_state = json.load(open(cls.statefile, 'r'))
            old_env = old_state.get('environment')

            # test if the old stack still exists ...
            if old_env and core.describe_stack(project + "--" + old_env,
                                               allow_missing=True):
                cls.state = old_state
                cls.environment = old_env
            else:
                # nope. old statefile is bogus, delete it
                os.unlink(cls.statefile)

        cls.state['environment'] = cls.environment  # will be saved later

        with settings(abort_on_prompts=True):
            cls.stackname = '%s--%s' % (project, cls.environment)
            cls.stacknames.append(cls.stackname)

            if cls.cleanup:
                LOG.info("ensure_destroyed %s", cls.stackname)
                cfn.ensure_destroyed(cls.stackname)

            cls.context, cls.cfn_template, _ = cfngen.generate_stack(
                project, stackname=cls.stackname)
            cls.region = cls.context['aws']['region']
            LOG.info("create_stack %s", cls.stackname)
            bootstrap.create_stack(cls.stackname)

            if explicitly_start:
                LOG.info("start %s", cls.stackname)
                lifecycle.start(cls.stackname)
예제 #12
0
def generate_stack_from_input(pname, instance_id=None, alt_config=None):
    """creates a new CloudFormation file for the given project."""
    instance_id = instance_id or utils.uin("instance id", core_utils.ymd())
    stackname = core.mk_stackname(pname, instance_id)
    checks.ensure_stack_does_not_exist(stackname)
    more_context = {'stackname': stackname}

    pdata = project.project_data(pname)
    if alt_config:
        ensure('aws-alt' in pdata, "alternative configuration name given, but project has no alternate configurations")

    # prompt user for alternate configurations
    if pdata['aws-alt']:
        default = 'skip'

        def helpfn(altkey):
            if altkey == default:
                return 'uses the default configuration'
            try:
                return pdata['aws-alt'][altkey]['description']
            except KeyError:
                return None
        if instance_id in pdata['aws-alt'].keys():
            LOG.info("instance-id found in known alternative configurations. using configuration %r", instance_id)
            more_context['alt-config'] = instance_id
        else:
            alt_config_choices = [default] + list(pdata['aws-alt'].keys())
            if not alt_config:
                alt_config = utils._pick('alternative config', alt_config_choices, helpfn=helpfn)
            if alt_config != default:
                more_context['alt-config'] = alt_config

    # TODO: return the templates used here, so that they can be passed down to
    # bootstrap.create_stack() without relying on them implicitly existing
    # on the filesystem
    cfngen.generate_stack(pname, **more_context)
    return stackname
예제 #13
0
    def set_up_stack(cls, project, explicitly_start=False):
        switch_in_test_settings()

        # to re-use an existing stack, ensure cls.reuse_existing_stack is True
        # this will read the instance name from a temporary file (if it exists) and
        # look for that, creating it if doesn't exist yet
        # also ensure cls.cleanup is False so the instance isn't destroyed after tests complete
        cls.reuse_existing_stack = config.TWI_REUSE_STACK
        cls.cleanup = config.TWI_CLEANUP

        cls.stacknames = []
        cls.environment = generate_environment_name()
        # cls.temp_dir, cls.rm_temp_dir = utils.tempdir()

        # debugging only, where we keep an instance up between processes
        cls.state, cls.statefile = {}, '/tmp/.open-test-instances.txt'

        if cls.reuse_existing_stack and os.path.exists(cls.statefile):
            # evidence of a previous instance and we've been told to re-use old instances
            old_state = json.load(open(cls.statefile, 'r'))
            old_env = old_state.get('environment')

            # test if the old stack still exists ...
            if old_env and core.describe_stack(project + "--" + old_env, allow_missing=True):
                cls.state = old_state
                cls.environment = old_env
            else:
                # nope. old statefile is bogus, delete it
                os.unlink(cls.statefile)

        cls.state['environment'] = cls.environment # will be saved later

        with settings(abort_on_prompts=True):
            cls.stackname = '%s--%s' % (project, cls.environment)
            cls.stacknames.append(cls.stackname)

            if cls.cleanup:
                LOG.info("ensure_destroyed %s", cls.stackname)
                cfn.ensure_destroyed(cls.stackname)

            cls.context, cls.cfn_template, _ = cfngen.generate_stack(project, stackname=cls.stackname)
            cls.region = cls.context['aws']['region']
            LOG.info("create_stack %s", cls.stackname)
            bootstrap.create_stack(cls.stackname)

            if explicitly_start:
                LOG.info("start %s", cls.stackname)
                lifecycle.start(cls.stackname)