示例#1
0
    def _validate(self):
        try:
            for key in self._config_dict.keys():
                assert str(key).lower() in ALLOWED_CONFIG_KEYS, \
                    "Invalid syntax, {0} is not allowed as top level config key".format(key)

            assert self.region, "Please specify region in config file"
            assert isinstance(
                self.region,
                str), "Region must be of type str, not {0}".format(
                    type(self.region))

            # stacks config file not required when executing a change set
            if self.change_set is None:
                assert self.stacks, "Please specify stacks in config file"
                assert isinstance(
                    self.stacks, TransformDict
                ), "stacks must be of type dict, not {0}".format(
                    type(self.stacks))

            for cli_stack in self.cli_params.keys():
                assert cli_stack in self.stacks.keys(
                ), "Stack '{0}' does not exist in config".format(cli_stack)

        except AssertionError as e:
            raise InvalidConfigException(e)
示例#2
0
    def _parse_stack_configs(self, config_dict, transform_context):
        """
        Create a StackConfig Object for each stack defined in config
        :param config_dict: dict
        :return: dict(stack_name: StackConfig)
        """
        stacks_dict = TransformDict({}, transform_context)
        for key, value in config_dict.get("stacks", {}).items():
            try:
                stacks_dict[key] = StackConfig(
                    value,
                    working_dir=self.working_dir,
                    default_tags=self.default_tags,
                    default_package_bucket=self.default_package_bucket,
                    default_timeout=self.default_timeout,
                    default_service_role=self.default_service_role,
                    default_stack_policy_url=self.default_stack_policy_url,
                    default_failure_action=self.default_failure_action,
                    default_disable_rollback=self.default_disable_rollback)

            except InvalidConfigException as e:
                raise InvalidConfigException(
                    "Invalid config for stack {0}: {1}".format(key, e))

        return stacks_dict
示例#3
0
    def _read_config_file(config_file):
        try:
            with open(config_file, "r") as f:
                config_dict = yaml.safe_load(f.read())
                if not isinstance(config_dict, dict):
                    raise InvalidConfigException(
                        "Config file {0} has invalid content, top level element must be a dict"
                        .format(config_file))

                return config_dict
        except ScannerError as e:
            raise InvalidConfigException("Could not parse {0}: {1} {2}".format(
                config_file, e.problem, e.problem_mark))
        except Exception as e:
            raise InvalidConfigException(
                "Could not read yaml file {0}: {1}".format(config_file, e))
示例#4
0
    def __init__(self, config_file=None, config_dict=None, cli_params=None):
        self.logger = get_logger()

        if isinstance(config_dict, dict):
            self.working_dir = None
        elif config_file:
            config_dict = self._read_config_file(config_file)
            self.working_dir = os.path.dirname(os.path.realpath(config_file))
        else:
            raise InvalidConfigException(
                "No config_file or valid config_dict provided")

        self.cli_params = self._parse_cli_parameters(cli_params)
        self.region = config_dict.get("region")

        self.default_service_role = config_dict.get("service-role")
        self.default_stack_policy_url = config_dict.get("stack-policy-url")
        self.default_timeout = config_dict.get("timeout", 600)
        self.default_tags = config_dict.get("tags", {})
        self.default_failure_action = config_dict.get("on_failure", "ROLLBACK")
        self.default_disable_rollback = config_dict.get(
            "disable_rollback", False)

        self.stacks = self._parse_stack_configs(config_dict)
        self._config_dict = config_dict

        self._validate()
示例#5
0
 def _validate_cli_params(cli_params, stacks):
     try:
         for cli_param_stack_name in cli_params.keys():
             assert cli_param_stack_name in stacks.keys(), \
                 "Stack '{0}' referenced in cli parameter does not exist in config".format(cli_param_stack_name)
     except AssertionError as e:
         raise InvalidConfigException(e)
示例#6
0
    def _validate(config_dict):
        try:
            for key in config_dict.keys():
                assert str(key).lower() in ALLOWED_CONFIG_KEYS, \
                    "Invalid syntax, {0} is not allowed as top level config key".format(key)

            region = config_dict.get("region")
            assert region, "Please specify region in config file"
            assert isinstance(
                region,
                string_types), "Region must be a string, not {0}".format(
                    type(region))

            stacks = config_dict.get("stacks")
            assert stacks, "Please specify stacks in config file"
            assert isinstance(
                stacks, dict), "Stacks must be of type dict, not {0}".format(
                    type(stacks))

            service_role = config_dict.get("service-role")
            if service_role:
                assert isinstance(
                    service_role, string_types
                ), "service-role must be of type str, not {0}".format(
                    type(service_role))
                assert service_role.startswith(
                    "arn:aws:iam"
                ), "service role must be an AWS ARN like arn:aws:iam::123456789:role/my-role"

        except AssertionError as e:
            raise InvalidConfigException(e)
示例#7
0
    def __init__(self,
                 config_file=None,
                 config_dict=None,
                 cli_params=None,
                 stack_name_suffix=None):
        self.logger = get_logger()

        if isinstance(config_dict, dict):
            self.stack_config_base_dir = None
        elif config_file:
            self.stack_config_base_dir = os.path.dirname(
                os.path.realpath(config_file))
            config_dict = FileLoader.get_yaml_or_json_file(
                config_file, working_dir=os.getcwd())
        else:
            raise InvalidConfigException(
                "You need to pass either config_file (path to a file) or config_dict (python dict) property"
            )

        self.cli_params = self._parse_cli_parameters(cli_params)
        self.region = config_dict.get("region")
        self.stack_name_suffix = stack_name_suffix

        self.default_service_role = config_dict.get("service-role")
        self.default_stack_policy_url = config_dict.get("stack-policy-url")
        self.default_timeout = config_dict.get("timeout", 600)
        self.default_tags = config_dict.get("tags", {})
        self.default_failure_action = config_dict.get("on_failure", "ROLLBACK")
        self.default_disable_rollback = config_dict.get(
            "disable_rollback", False)

        self._validate(config_dict)

        stacks = self._parse_stack_configs(config_dict)
        self.stacks = self._apply_stack_name_suffix(stacks, stack_name_suffix)
示例#8
0
    def __init__(self,
                 config_file=None,
                 config_dict=None,
                 cli_params=None,
                 transform_context=None):
        self.logger = get_logger()

        import_path = None

        if transform_context:
            import_path = os.path.dirname(transform_context)

            with open(transform_context, 'r') as stream:
                transform_context = yaml.load(stream)
        else:
            transform_context = {}

        if isinstance(config_dict, dict):
            self.working_dir = None
        elif config_file:
            config_dict = self._read_config_file(config_file,
                                                 transform_context,
                                                 import_path)
            self.working_dir = os.path.dirname(os.path.realpath(config_file))
        else:
            raise InvalidConfigException(
                "No config_file or valid config_dict provided")

        self.cli_params = self._parse_cli_parameters(cli_params)
        self.region = config_dict.get("region")

        self.change_set = config_dict.get("change_set")
        self.default_service_role = config_dict.get("service-role")
        self.default_stack_policy_url = config_dict.get("stack-policy-url")
        self.default_timeout = config_dict.get("timeout", 600)
        self.default_tags = config_dict.get("tags", {})
        self.default_package_bucket = config_dict.get("package-bucket", None)
        self.default_failure_action = config_dict.get("on_failure", "ROLLBACK")
        self.default_disable_rollback = config_dict.get(
            "disable_rollback", False)

        self.stacks = self._parse_stack_configs(config_dict, transform_context)
        self._config_dict = config_dict

        self._validate()
示例#9
0
    def _validate(self):
        try:
            for key in self._stack_config_dict.keys():
                assert str(key).lower() in self.STACK_CONFIG_ALLOWED_CONFIG_KEYS, \
                    "Invalid syntax, {0} is not allowed as stack config key".format(key)

            assert self.template_url, "Stack config needs a template-url key"
            assert isinstance(self.template_url, str), \
                "template-url must be of type str, not {0}".format(type(self.template_url))

            assert isinstance(
                self.timeout,
                int), "timeout must be of type dict, not {0}".format(
                    type(self.timeout))

            if self.package_bucket:
                assert isinstance(self.package_bucket, str), \
                    "package-bucket must be of type str, not {0}".format(type(self.package_bucket))

            if self.service_role:
                assert isinstance(self.service_role, str), \
                    "service-role must be of type str, not {0}".format(type(self.template_url))
                assert str(self.service_role).lower().startswith("arn:aws:iam:"), \
                    "service-role must start with 'arn:aws:iam:'"

            if self.stack_policy_url:
                assert isinstance(self.stack_policy_url, str), \
                    "stack-policy-url must be of type str, not {0}".format(type(self.stack_policy_url))

            if self.timeout:
                assert isinstance(self.timeout, int), \
                    "timeout must be of type int, not {0}".format(type(self.timeout))

            if self.failure_action:
                assert str(self.failure_action).lower() in ['do_nothing', 'rollback', 'delete'], \
                    "on_failure property value must be one of 'DO_NOTHING'|'ROLLBACK'|'DELETE'"

            if self.disable_rollback:
                assert isinstance(
                    self.disable_rollback,
                    bool), "disable_rollback property value must be a boolean"

        except AssertionError as e:
            raise InvalidConfigException(e)
示例#10
0
    def __init__(self,
                 stack_config_dict,
                 working_dir=None,
                 default_tags=None,
                 default_package_bucket=None,
                 default_timeout=600,
                 default_service_role=None,
                 default_stack_policy_url=None,
                 default_failure_action="ROLLBACK",
                 default_disable_rollback=False):

        # unit testing constructs this directly which means we have to wrap it here.
        if not isinstance(stack_config_dict, TransformDict):
            stack_config_dict = TransformDict(stack_config_dict, {})

        if not stack_config_dict:
            raise InvalidConfigException(
                "Stack configuration must not be empty")

        if default_tags is None:
            default_tags = {}
        self.parameters = stack_config_dict.get("parameters", {})
        self.template_url = stack_config_dict.get("template-url")

        self.tags = {}
        self.tags.update(default_tags)
        self.tags.update(stack_config_dict.get("tags", {}))

        self.package_bucket = stack_config_dict.get("package-bucket",
                                                    default_package_bucket)
        self.service_role = stack_config_dict.get("service-role",
                                                  default_service_role)
        self.stack_policy_url = stack_config_dict.get(
            "stack-policy-url", default_stack_policy_url)
        self.timeout = stack_config_dict.get("timeout", default_timeout)
        self.failure_action = stack_config_dict.get("on_failure",
                                                    default_failure_action)
        self.disable_rollback = stack_config_dict.get(
            "disable_rollback", default_disable_rollback)

        self.working_dir = working_dir
        self._stack_config_dict = stack_config_dict

        self._validate()
示例#11
0
    def __init__(self,
                 stack_config_dict,
                 working_dir=None,
                 default_tags=None,
                 default_timeout=600,
                 default_service_role=None,
                 default_stack_policy_url=None,
                 default_failure_action="ROLLBACK",
                 default_disable_rollback=False,
                 default_termination_protection=False):

        if not stack_config_dict or not isinstance(stack_config_dict, dict):
            raise InvalidConfigException(
                "Stack configuration must not be empty")

        if default_tags is None:
            default_tags = {}
        self.parameters = stack_config_dict.get("parameters", {})
        self.template_url = stack_config_dict.get("template-url")

        self.tags = {}
        self.tags.update(default_tags)
        self.tags.update(stack_config_dict.get("tags", {}))

        self.service_role = stack_config_dict.get("service-role",
                                                  default_service_role)
        self.stack_policy_url = stack_config_dict.get(
            "stack-policy-url", default_stack_policy_url)
        self.timeout = stack_config_dict.get("timeout", default_timeout)
        self.failure_action = stack_config_dict.get("on_failure",
                                                    default_failure_action)
        self.disable_rollback = stack_config_dict.get(
            "disable_rollback", default_disable_rollback)
        self.termination_protection = stack_config_dict.get(
            "termination_protection", default_termination_protection)

        self.working_dir = working_dir
        self._stack_config_dict = stack_config_dict

        self._validate()
示例#12
0
    def _validate(self, config_dict):
        try:
            for key in config_dict.keys():
                assert str(key).lower() in ALLOWED_CONFIG_KEYS, \
                    "Invalid syntax, {0} is not allowed as top level config key".format(key)

            assert self.region, "Please specify region in config file"
            assert isinstance(
                self.region,
                string_types), "Region must be a string, not {0}".format(
                    type(self.region))

            stacks = config_dict.get("stacks")
            assert stacks, "Please specify stacks in config file"
            assert isinstance(
                stacks, dict), "Stacks must be of type dict, not {0}".format(
                    type(stacks))

            for cli_param_stack_name in self.cli_params.keys():
                assert cli_param_stack_name in stacks.keys(), \
                    "Stack '{0}' referenced in cli parameter does not exist in config".format(cli_param_stack_name)

        except AssertionError as e:
            raise InvalidConfigException(e)