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