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
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
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
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)
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
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
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
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)
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"))
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
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)
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
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)