def test_tag(self): tag_dict = {"Key": "my_key", "Value": "my_value"} tag = Tag(tag_dict) self.assertEqual(tag.key, "my_key") self.assertEqual(tag.value, "my_value") actual = tag.dump() self.assertEqual(tag_dict, actual)
def create_stacks(self, threads: int = 8): if self.stacks: raise TaskCatException( "Stacker already initialised with stack objects") tests = self._tests_to_list(self.config.tests) tags = [Tag({"Key": "taskcat-id", "Value": self.uid.hex})] tags += [ Tag(t) for t in self.tags if t.key not in ["taskcat-project-name", "taskcat-test-name", "taskcat-id"] ] fan_out(self._create_stacks_for_test, {"tags": tags}, tests, threads)
def _create_stacks_for_test(self, test, tags, threads: int = 32): prefix = f"{self.stack_name_prefix}-" if self.stack_name_prefix else "" stack_name = "{}{}-{}-{}".format(prefix, self.project_name, test.name, self.uid.hex) tags.append( Tag({ "Key": "taskcat-project-name", "Value": self.project_name })) tags.append(Tag({"Key": "taskcat-test-name", "Value": test.name})) partial_kwargs = { "stack_name": stack_name, "template": test.template, "tags": tags, "test_name": test.name, } stacks = fan_out(Stack.create, partial_kwargs, test.regions, threads) self.stacks += stacks
def test_filterable_list(self): tags = Tags([Tag({"Key": "my_key", "Value": "my_value"})]) filtered = tags.filter() self.assertEqual(filtered, tags) filtered = tags.filter({"key": "blah"}) self.assertEqual(filtered, []) filtered = tags.filter({"key": "my_key"}) self.assertEqual(filtered, tags) filtered = tags.filter(key="my_key", value="blah") self.assertEqual(filtered, []) filtered = tags.filter(key="my_key", value="my_value") self.assertEqual(filtered, tags)
def test_criteria_matches(self): with self.assertRaises(ValueError) as cm: tag = Tag({"Key": "my_key", "Value": "my_value"}) criteria_matches({"invalid": "blah"}, tag) self.assertEqual( "invalid is not a valid property of <class 'taskcat._cfn.stack.Tag'>", str(cm.exception), ) actual = criteria_matches({"key": "blah"}, tag) self.assertEqual(actual, False) actual = criteria_matches({"key": "my_key"}, tag) self.assertEqual(actual, True) actual = criteria_matches({"key": "my_key", "value": "blah"}, tag) self.assertEqual(actual, False) actual = criteria_matches({"key": "my_key", "value": "my_value"}, tag) self.assertEqual(actual, True)
def __init__( # noqa: C901 self, package: str, aws_profile: str = "default", region="default", parameters="", name="", wait=False, ): """ :param package: name of package to install can be a path to a local package, a github org/repo, or an AWS Quick Start name :param aws_profile: aws profile to use for installation :param region: regions to install into, default will use aws cli configured default :param parameters: parameters to pass to the stack, in the format Key=Value,AnotherKey=AnotherValue or providing a path to a json or yaml file containing the parameters :param name: stack name to use, if not specified one will be automatically generated :param wait: if enabled, taskcat will wait for stack to complete before exiting """ LOG.warning("deploy is in alpha feature, use with caution") boto3_cache = Boto3Cache() if not name: name = generate_name() if region == "default": region = boto3_cache.get_default_region(profile_name=aws_profile) path = Path(package).resolve() if Path(package).resolve().is_dir(): package_type = "local" elif "/" in package: package_type = "github" else: # assuming it's an AWS Quick Start package_type = "github" package = f"aws-quickstart/quickstart-{package}" if package_type == "github": if package.startswith("https://") or package.startswith("git@"): url = package org, repo = (package.replace(".git", "").replace(":", "/").split("/")[-2:]) else: org, repo = package.split("/") url = f"https://github.com/{org}/{repo}.git" path = Deploy.PKG_CACHE_PATH / org / repo LOG.info(f"fetching git repo {url}") self._git_clone(url, path) self._recurse_submodules(path, url) config = Config.create( args={"project": { "regions": [region] }}, project_config_path=(path / ".taskcat.yml"), project_root=path, ) # only use one region for test_name in config.config.tests: config.config.tests[ test_name].regions = config.config.project.regions # if there's no test called default, take the 1st in the list if "default" not in config.config.tests: config.config.tests["default"] = config.config.tests[list( config.config.tests.keys())[0]] # until install offers a way to run different "plans" we only need one test for test_name in list(config.config.tests.keys()): if test_name != "default": del config.config.tests[test_name] buckets = config.get_buckets(boto3_cache) stage_in_s3(buckets, config.config.project.name, path) regions = config.get_regions(boto3_cache) templates = config.get_templates(project_root=path) parameters = config.get_rendered_parameters(buckets, regions, templates) tests = config.get_tests(path, templates, regions, buckets, parameters) tags = [Tag({"Key": "taskcat-installer", "Value": name})] stacks = Stacker(config.config.project.name, tests, tags=tags) stacks.create_stacks() LOG.error( f" {stacks.uid.hex}", extra={"nametag": "\x1b[0;30;47m[INSTALL_ID ]\x1b[0m"}, ) LOG.error(f" {name}", extra={"nametag": "\x1b[0;30;47m[INSTALL_NAME]\x1b[0m"}) if wait: LOG.info( f"waiting for stack {stacks.stacks[0].name} to complete in " f"{stacks.stacks[0].region_name}") while stacks.status()["IN_PROGRESS"]: sleep(5) if stacks.status()["FAILED"]: LOG.error("Install failed:") for error in stacks.stacks[0].error_events(): LOG.error(f"{error.logical_id}: {error.status_reason}") raise TaskCatException("Stack creation failed")