class acl_grant_spec(statement_spec): args = lambda s, self_type, self_name: { "grantee": sb.or_spec(sb.string_choice_spec(["__owner__"]), acl_grantee_spec("grantee", "grantee")), "permission": sb.string_choice_spec( ["READ", "WRITE", "READ_ACP", "WRITE_ACP", "FULL_CONTROL"]) } required = ["grantee", "permission"] def final_kls(self, *args, **kwargs): def ret(owner): result = { "Grantee": kwargs["grantee"], "Permission": kwargs["permission"] } if isinstance(kwargs['grantee'], six.string_types): if result["Grantee"] == "__owner__": result["Grantee"] = owner else: raise BadOption("Don't know how to deal with this grantee", grantee=kwargs['grantee']) return result return ret
def alerting_system_spec(self): return create_spec(stack_objs.AlertingSystem , name = formatted(overridden("{_key_name_1}"), formatter=MergedOptionStringFormatter) , type = string_choice_spec(["nagios"]) , endpoint = required(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , verify_ssl = defaulted(boolean(), True) )
def normalise(self, meta, val): if 'use' in val: template = val['use'] if template not in meta.everything['templates']: available = list(meta.everything['templates'].keys()) raise BadTemplate("Template doesn't exist!", wanted=template, available=available, meta=meta) val = MergedOptions.using(meta.everything['templates'][template], val) formatted_string = sb.formatted(sb.string_spec(), MergedOptionStringFormatter) route_name = meta.key_names()['_key_name_0'] val = sb.create_spec(DNSRoute , name = sb.overridden(route_name) , zone = formatted_string , record_type = sb.string_choice_spec(["CNAME"]) , record_target = formatted_string ).normalise(meta, val) if not val.zone.endswith("."): val.zone = "{0}.".format(val.zone) if not isinstance(val.record_target, six.string_types): if not hasattr(val.record_target, "cname"): raise BadSpecValue("record_target must point at an object with a cname property", got=type(val.record_target), meta=meta) val.record_target = val.record_target.cname return val
def normalise(self, meta, val): canned_acls = [ "private", "public-read", "public-read-write", "aws-exec-read" , "authenticated-read", "log-delivery-write" ] acl = sb.defaulted( sb.formatted(sb.string_choice_spec(canned_acls), formatter=MergedOptionStringFormatter) , "private" ).normalise(meta, val) def ret(owner): """http://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#canned-acl""" if acl == "private": new_grants = [Acls.FullControl(owner)] elif acl == "public-read": new_grants = [Acls.FullControl(owner), Acls.Read(Acls.AllUsersGroup)] elif acl == "public-read-write": new_grants = [Acls.FullControl(owner), Acls.Read(Acls.AllUsersGroup), Acls.Write(Acls.AllUsersGroup)] elif acl == "aws-exec-read": new_grants = [Acls.FullControl(owner), Acls.Read(Acls.EC2Group)] elif acl == "authenticated-read": new_grants = [Acls.FullControl(owner), Acls.Read(Acls.AuthenticatedUsersGroup)] elif acl == "log-delivery-write": new_grants = [Acls.FullControl(owner), Acls.Write(Acls.LogDeliveryGroup), Acls.ReadACP(Acls.LogDeliveryGroup)] return {"ACL": acl, "AccessControlPolicy": {"Grants": new_grants}} return ret
def normalise(self, meta, val): accounts = list(self.accounts(meta)) if not accounts: accounts = [self.default_account_id(meta)] for account_id in accounts: string_or_dict = sb.or_spec(sb.string_spec(), sb.dictof(sb.string_choice_spec(["key_id", "alias"]), sb.string_spec())) for key_id in sb.listof(string_or_dict).normalise(meta, val): alias = None if key_id == "__self__" or (isinstance(key_id, dict) and (key_id.get("alias") == "__self__" or key_id.get("key_id") == "__self__")): if self.self_type != "key": raise BadPolicy("No __self__ key for this policy", meta=meta) else: alias = self.self_name location = self.default_location(meta) else: location = self.location(meta) if not alias: if isinstance(key_id, six.string_types): alias = key_id else: alias = key_id.get("alias") key_id = key_id.get("key_id") if alias: yield "arn:aws:kms:{0}:{1}:alias/{2}".format(location, account_id, alias) else: yield "arn:aws:kms:{0}:{1}:key/{2}".format(location, account_id, key_id)
def alerting_system_spec(self): return create_spec(stack_objs.AlertingSystem , name = formatted(overridden("{_key_name_1}"), formatter=MergedOptionStringFormatter) , type = string_choice_spec(["nagios"]) , endpoint = required(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , verify_ssl = defaulted(boolean(), True) )
def setup(self, **kwargs): kwargs = sb.set_options( app_id = sb.required(sb.string_or_int_as_string_spec()) , itunes_country_code = sb.required(sb.string_choice_spec(["au"])) ).normalise(Meta({}, []), kwargs) for key, val in kwargs.items(): setattr(self, key, val)
def tasks_spec(self, available_actions, default_action="run"): """Tasks for a particular stack""" return dictof( self.task_name_spec , create_spec(task_objs.Task , action = defaulted(string_choice_spec(available_actions, "No such task"), default_action) , options = dictionary_spec() , overrides = dictionary_spec() , description = string_spec() ) )
class transition_spec(statement_spec): args = lambda s, self_type, self_name: { "days": sb.optional_spec(sb.integer_spec()), "date": capitalized_only_spec(), ("storage", "class"): sb.string_choice_spec(["GLACIER", "STANDARD_IA"]) } required = ["storageclass"] conflicting = [('days', 'date')] validators = [validators.has_either(["days", "Days", "date", "Date"])] final_kls = lambda s, *args, **kwargs: LifecycleTransitionConfig( *args, **kwargs)
def tasks_spec(self, available_actions, default_action="run"): """Tasks for a particular stack""" return dictof( self.task_name_spec , create_spec(task_objs.Task , action = defaulted(string_choice_spec(available_actions, "No such task"), default_action) , options = dictionary_spec() , overrides = dictionary_spec() , description = string_spec() ) )
def tasks_spec(self, available_actions, default_action="run"): """Tasks for a particular image""" return dictof( self.task_name_spec , create_spec(task_objs.Task, validators.deprecated_key("spec", "Use ``action`` and ``options`` instead (note that ``action`` defaults to run)") , action = defaulted(string_choice_spec(available_actions, "No such task"), default_action) , options = dictionary_spec() , overrides = dictionary_spec() , description = string_spec() ) )
def normalise_filled(self, meta, val): val = sb.dictof(sb.string_choice_spec(["s3", "inline", "directory"]), sb.any_spec()).normalise(meta, val) if not val: raise BadSpecValue( "Please specify s3, inline or directory for your code", meta=meta) if len(val) > 1: raise BadSpecValue( "Please only specify one of s3, inline or directory for your code", got=list(val.keys()), meta=meta) formatted_string = sb.formatted(sb.string_spec(), formatter=MergedOptionStringFormatter) if "s3" in val: return sb.create_spec( S3Code, key=formatted_string, bucket=formatted_string, version=sb.defaulted(sb.string_spec(), NotSpecified)).normalise(meta, val['s3']) elif "inline" in val: path = [p for p, _ in meta._path] path.pop() runtime = meta.everything['.'.join(path)].get("runtime", "python") runtime = sb.formatted( sb.string_spec(), formatter=MergedOptionStringFormatter).normalise( meta.at("runtime"), runtime) return sb.create_spec(InlineCode, code=sb.string_spec(), runtime=sb.overridden(runtime)).normalise( meta, {"code": val['inline']}) else: directory = val['directory'] if isinstance(val['directory'], six.string_types): directory = {"directory": val['directory']} if 'directory' in directory: formatted_string = sb.formatted( sb.string_spec(), formatter=MergedOptionStringFormatter) directory['directory'] = formatted_string.normalise( meta.at("directory").at("directory"), directory['directory']) return sb.create_spec(DirectoryCode, directory=sb.directory_spec(), exclude=sb.listof( sb.string_spec())).normalise( meta, directory)
class BackgroundOption(dictobj.Spec): type = dictobj.Field(sb.string_choice_spec(["specified", "current"]), default="specified") hue = dictobj.Field(sb.float_spec, default=0) saturation = dictobj.Field(sb.float_spec, default=0) brightness = dictobj.Field(sb.float_spec, default=0) kelvin = dictobj.Field(sb.float_spec, default=3500) @property def default_color(self): return Color(self.hue, self.saturation, self.brightness, self.kelvin)
def normalise(self, meta, val): canned_acls = [ "private", "public-read", "public-read-write", "aws-exec-read", "authenticated-read", "log-delivery-write" ] acl = sb.defaulted( sb.formatted(sb.string_choice_spec(canned_acls), formatter=MergedOptionStringFormatter), "private").normalise(meta, val) def ret(owner): """http://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#canned-acl""" if acl == "private": new_grants = [Acls.FullControl(owner)] elif acl == "public-read": new_grants = [ Acls.FullControl(owner), Acls.Read(Acls.AllUsersGroup) ] elif acl == "public-read-write": new_grants = [ Acls.FullControl(owner), Acls.Read(Acls.AllUsersGroup), Acls.Write(Acls.AllUsersGroup) ] elif acl == "aws-exec-read": new_grants = [ Acls.FullControl(owner), Acls.Read(Acls.EC2Group) ] elif acl == "authenticated-read": new_grants = [ Acls.FullControl(owner), Acls.Read(Acls.AuthenticatedUsersGroup) ] elif acl == "log-delivery-write": new_grants = [ Acls.FullControl(owner), Acls.Write(Acls.LogDeliveryGroup), Acls.ReadACP(Acls.LogDeliveryGroup) ] return {"ACL": acl, "AccessControlPolicy": {"Grants": new_grants}} return ret
def normalise(self, meta, val): # Make sure we have integration integration_spec = sb.required(sb.string_choice_spec(["aws", "mock"])) sb.set_options(integration=integration_spec).normalise(meta, val) # Determine the http method and resource name method = meta.key_names()["_key_name_0"] resource_name = meta.key_names()["_key_name_2"] # We have integration if no exception was raised if val['integration'] == "aws": return aws_resource_spec(method, resource_name).normalise(meta, val) else: return mock_resource_spec(method, resource_name).normalise(meta, val)
def normalise(self, meta, val): # Make sure we have integration integration_spec = sb.required(sb.string_choice_spec(["aws", "mock"])) sb.set_options(integration=integration_spec).normalise(meta, val) # Determine the http method and resource name method = meta.key_names()["_key_name_0"] resource_name = meta.key_names()["_key_name_2"] # We have integration if no exception was raised if val['integration'] == "aws": return aws_resource_spec(method, resource_name).normalise(meta, val) else: return mock_resource_spec(method, resource_name).normalise(meta, val)
class TileGameOfLifeOptions(AnimationOptions): user_coords = dictobj.Field(sb.boolean, default=True) num_iterations = dictobj.Field(sb.integer_spec, default=-1) new_color_style = dictobj.Field(sb.string_choice_spec(["random", "average"]), default="average") iteration_delay = dictobj.Field(sb.float_spec, default=0.1) def final_iteration(self, iteration): if self.num_iterations == -1: return False return self.num_iterations <= iteration def make_new_color(self, surrounding): if self.new_color_style == "random": return Color(random.randrange(0, 360), 1, 1, 3500) else: return Color.average(surrounding)
def tasks_spec(self, available_actions, default_action="run"): """Tasks for a particular image""" return dictof( self.task_name_spec, create_spec( task_objs.Task, validators.deprecated_key( "spec", "Use ``action`` and ``options`` instead (note that ``action`` defaults to run)" ), action=defaulted( string_choice_spec(available_actions, "No such task"), default_action), options=dictionary_spec(), overrides=dictionary_spec(), description=string_spec()))
def normalise_filled(self, meta, value): # Make sure the value is a dictionary with a 'use' option set_options(use=required(string_choice_spec(["kms", "plain", "s3_slip"]))).normalise(meta, value) use = value["use"] formatted_string = formatted(string_spec(), formatter=MergedOptionStringFormatter) if use == "kms" or use == "plain" : kls = authentication_objs.PlainAuthentication if use == "plain" else authentication_objs.KmsAuthentication spec = dict(username=required(formatted_string), password=required(formatted_string)) if use == "kms": spec.update(role=required(formatted_string), region=required(formatted_string)) elif use == "s3_slip": kls = authentication_objs.S3SlipAuthentication spec = dict(role=required(formatted_string), location=required(formatted_string)) return create_spec(kls, **spec).normalise(meta, value)
class Options(dictobj.Spec): colors = dictobj.Field(sb.listof(Color.FieldSpec()), wrapper=sb.required) theme = dictobj.Field(sb.string_choice_spec(appliers.keys()), default="SPLOTCH") duration = dictobj.Field(sb.float_spec(), default=1) hue = dictobj.NullableField(sb.float_spec()) saturation = dictobj.NullableField(sb.float_spec()) brightness = dictobj.NullableField(sb.float_spec()) kelvin = dictobj.NullableField(sb.float_spec()) @property def overrides(self): o = {} for key in ("duration", "hue", "saturation", "brightness", "kelvin"): if self[key] is not None: o[key] = self[key] return o
class resource_policy_statement_spec(statement_spec): args = lambda s, self_type, self_name: { 'sid': sb.string_spec(), 'effect': sb.string_choice_spec(choices=["Deny", "Allow"]), 'action': sb.listof(sb.string_spec()), ("not", "action"): sb.listof(sb.string_spec()), 'resource': resource_spec(self_type, self_name), ('not', 'resource'): resource_spec(self_type, self_name), 'principal': sb.listof(principal_spec(self_type, self_name)), ('not', 'principal'): sb.listof(principal_spec(self_type, self_name)), 'condition': sb.dictionary_spec(), ('not', 'condition'): sb.dictionary_spec() } validators = [ validators.deprecated_key('allow', "Use 'effect: Allow|Deny' instead"), validators.deprecated_key('disallow', "Use 'effect: Allow|Deny' instead") ] final_kls = lambda s, *args, **kwargs: ResourcePolicyStatement( *args, **kwargs)
class acl_grantee_spec(statement_spec): formatted_string = sb.formatted(sb.string_spec(), formatter=MergedOptionStringFormatter) args = lambda s, self_type, self_name: { (("sep", "_"), ("parts", ("display", "name"))): s.formatted_string, "id": s.formatted_string, "type": sb.string_choice_spec(["Group", "CanonicalUser"]), ("u", "r", "i"): s.formatted_string } required = ["type"] def final_kls(self, *args, **kwargs): result = { "ID": kwargs['id'], "DisplayName": kwargs["display_name"], "Type": kwargs["type"], "URI": kwargs["uri"] } return dict((key, val) for key, val in result.items() if val is not NotSpecified)
def normalise(self, meta, val): accounts = list(self.accounts(meta)) if not accounts: accounts = [self.default_account_id(meta)] for account_id in accounts: string_or_dict = sb.or_spec( sb.string_spec(), sb.dictof(sb.string_choice_spec(["key_id", "alias"]), sb.string_spec())) for key_id in sb.listof(string_or_dict).normalise(meta, val): alias = None if key_id == "__self__" or ( isinstance(key_id, dict) and (key_id.get("alias") == "__self__" or key_id.get("key_id") == "__self__")): if self.self_type != "key": raise BadPolicy("No __self__ key for this policy", meta=meta) else: alias = self.self_name location = self.default_location(meta) else: location = self.location(meta) if not alias: if isinstance(key_id, six.string_types): alias = key_id else: alias = key_id.get("alias") key_id = key_id.get("key_id") if alias: yield "arn:aws:kms:{0}:{1}:alias/{2}".format( location, account_id, alias) else: yield "arn:aws:kms:{0}:{1}:key/{2}".format( location, account_id, key_id)
def normalise_filled(self, meta, val): val = sb.dictof(sb.string_choice_spec(["s3", "inline", "directory"]), sb.any_spec()).normalise(meta, val) if not val: raise BadSpecValue("Please specify s3, inline or directory for your code", meta=meta) if len(val) > 1: raise BadSpecValue("Please only specify one of s3, inline or directory for your code", got=list(val.keys()), meta=meta) formatted_string = sb.formatted(sb.string_spec(), formatter=MergedOptionStringFormatter) if "s3" in val: return sb.create_spec(S3Code , key = formatted_string , bucket = formatted_string , version = sb.defaulted(sb.string_spec(), NotSpecified) ).normalise(meta, val['s3']) elif "inline" in val: path = [p for p, _ in meta._path] path.pop() runtime = meta.everything['.'.join(path)].get("runtime", "python") runtime = sb.formatted(sb.string_spec(), formatter=MergedOptionStringFormatter).normalise(meta.at("runtime"), runtime) return sb.create_spec(InlineCode , code = sb.string_spec() , runtime = sb.overridden(runtime) ).normalise(meta, {"code": val['inline']}) else: directory = val['directory'] if isinstance(val['directory'], six.string_types): directory = {"directory": val['directory']} if 'directory' in directory: formatted_string = sb.formatted(sb.string_spec(), formatter=MergedOptionStringFormatter) directory['directory'] = formatted_string.normalise(meta.at("directory").at("directory"), directory['directory']) return sb.create_spec(DirectoryCode , directory = sb.directory_spec() , exclude = sb.listof(sb.string_spec()) ).normalise(meta, directory)
def normalise_filled(self, meta, value): # Make sure the value is a dictionary with a 'use' option set_options(use=required( string_choice_spec(["kms", "plain", "s3_slip"]))).normalise( meta, value) use = value["use"] formatted_string = formatted(string_spec(), formatter=MergedOptionStringFormatter) if use == "kms" or use == "plain": kls = authentication_objs.PlainAuthentication if use == "plain" else authentication_objs.KmsAuthentication spec = dict(username=required(formatted_string), password=required(formatted_string)) if use == "kms": spec.update(role=required(formatted_string), region=required(formatted_string)) elif use == "s3_slip": kls = authentication_objs.S3SlipAuthentication spec = dict(role=required(formatted_string), location=required(formatted_string)) return create_spec(kls, **spec).normalise(meta, value)
def normalise(self, meta, val): if 'use' in val: template = val['use'] if template not in meta.everything['templates']: available = list(meta.everything['templates'].keys()) raise BadTemplate("Template doesn't exist!", wanted=template, available=available, meta=meta) val = MergedOptions.using(meta.everything['templates'][template], val) formatted_string = sb.formatted(sb.string_spec(), MergedOptionStringFormatter) route_name = meta.key_names()['_key_name_0'] val = sb.create_spec(DNSRoute, name=sb.overridden(route_name), zone=formatted_string, record_type=sb.string_choice_spec(["CNAME"]), record_target=formatted_string).normalise( meta, val) if not val.zone.endswith("."): val.zone = "{0}.".format(val.zone) if not isinstance(val.record_target, six.string_types): if not hasattr(val.record_target, "cname"): raise BadSpecValue( "record_target must point at an object with a cname property", got=type(val.record_target), meta=meta) val.record_target = val.record_target.cname return val
def stack_spec(self): """Spec for each stack""" return create_spec(stack_objs.Stack , validators.deprecated_key("url_checker", "Use ``confirm_deployment.url_checker1``") , validators.deprecated_key("deploys_s3_path", "Use ``confirm_deployment.deploys_s3_path``") , validators.deprecated_key("sns_confirmation", "Use ``confirm_deployment.sns_confirmation``") , validators.deprecated_key("autoscaling_group_id", "Use ``auto_scaling_group_name``") , validators.deprecated_key("instance_count_limit", "Use ``scaling_options.instance_count_limit``") , bespin = any_spec() , name = formatted(defaulted(string_spec(), "{_key_name_1}"), formatter=MergedOptionStringFormatter) , key_name = formatted(overridden("{_key_name_1}"), formatter=MergedOptionStringFormatter) , stack_name = formatted(defaulted(string_spec(), "{_key_name_1}"), formatter=MergedOptionStringFormatter) , environment = formatted(overridden("{environment}"), formatter=MergedOptionStringFormatter) , env = listof(stack_specs.env_spec(), expect=stack_objs.Environment) , build_env = listof(stack_specs.env_spec(), expect=stack_objs.Environment) , stack_name_env = listof(stack_specs.env_spec(), expect=stack_objs.Environment) , tags = dictionary_spec() , stack_json = valid_stack_json(default="{config_root}/{_key_name_1}.json") , params_json = valid_params_json(default="{config_root}/{environment}/{_key_name_1}-params.json") , params_yaml = valid_params_yaml(default="{config_root}/{environment}/{_key_name_1}-params.yaml") , build_first = listof(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , build_after = listof(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , build_timeout = defaulted(integer_spec(), 1200) , ignore_deps = defaulted(boolean(), False) , vars = dictof(string_spec(), stack_specs.var_spec(), nested=True) , skip_update_if_equivalent = listof(stack_specs.skipper_spec()) , suspend_actions = defaulted(boolean(), False) , auto_scaling_group_name = optional_spec(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , artifact_retention_after_deployment = defaulted(boolean(), False) , command = optional_spec(string_spec()) , netscaler = optional_spec(self.netscaler_spec) , dns = optional_spec(stack_specs.dns_spec(create_spec(stack_objs.DNS , vars = dictof(string_spec(), formatted(string_spec(), formatter=MergedOptionStringFormatter), nested=True) , providers = dictof(string_spec(), stack_specs.dns_provider_spec()) , sites = delayed(dictof(string_spec(), stack_specs.dns_site_spec())) ))) , scaling_options = create_spec(ScalingOptions , highest_min = defaulted(integer_spec(), 2) , instance_count_limit = defaulted(integer_spec(), 10) ) , artifacts = container_spec(artifact_objs.ArtifactCollection, dictof(string_spec(), create_spec(artifact_objs.Artifact , not_created_here = defaulted(boolean(), False) , compression_type = string_choice_spec(["gz", "xz"]) , history_length = integer_spec() , cleanup_prefix = optional_spec(string_spec()) , upload_to = formatted(string_spec(), formatter=MergedOptionStringFormatter) , commands = listof(stack_specs.artifact_command_spec(), expect=artifact_objs.ArtifactCommand) , paths = listof(stack_specs.artifact_path_spec(), expect=artifact_objs.ArtifactPath) , files = listof(create_spec(artifact_objs.ArtifactFile, validators.has_either(["content", "task"]) , content = optional_spec(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , task = optional_spec(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , path = formatted(string_spec(), formatter=MergedOptionStringFormatter) , task_runner = formatted(always_same_spec("{task_runner}"), formatter=MergedOptionStringFormatter) )) ))) , newrelic = optional_spec(create_spec(stack_objs.NewRelic , api_key = required(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , account_id = required(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , application_id = required(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , env = listof(stack_specs.env_spec(), expect=stack_objs.Environment) , deployed_version = required(formatted(string_spec(), formatter=MergedOptionStringFormatter)) )) , downtimer_options = optional_spec(dictof(valid_string_spec(valid_alerting_system()) , create_spec(stack_objs.DowntimerOptions , hosts = listof(formatted(string_spec(), formatter=MergedOptionStringFormatter)) ) )) , alerting_systems = optional_spec(dictof(string_spec(), self.alerting_system_spec)) , ssh = optional_spec(create_spec(stack_objs.SSH , validators.deprecated_key("autoscaling_group_id", "Use ``auto_scaling_group_name``") , user = required(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , bastion = optional_spec(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , bastion_user = required(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , bastion_key_location = optional_spec(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , instance_key_location = optional_spec(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , address = optional_spec(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , instance = optional_spec(listof(formatted(string_spec(), formatter=MergedOptionStringFormatter))) , auto_scaling_group_name = optional_spec(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , bastion_key_path = formatted(defaulted(string_spec(), "{config_root}/{environment}/bastion_ssh_key.pem"), formatter=MergedOptionStringFormatter) , instance_key_path = formatted(defaulted(string_spec(), "{config_root}/{environment}/ssh_key.pem"), formatter=MergedOptionStringFormatter) , storage_type = formatted(defaulted(string_choice_spec(["url", "rattic"]), "url"), formatter=MergedOptionStringFormatter) , storage_host = optional_spec(formatted(string_spec(), formatter=MergedOptionStringFormatter)) )) , confirm_deployment = optional_spec(self.confirm_deployment_spec) )
Strip ``NotSpecified`` values from normalised dictionary and ensure only one of the 'Not' options are specified """ def normalise_filled(self, meta, val): result = super(policy_set_options, self).normalise_filled(meta, val) val = dict((k, v) for k, v in result.items() if v is not NotSpecified) return sb.apply_validators(meta, val, [ validators.has_only_one_of(["Action", "NotAction"]), validators.has_only_one_of(["Resource", "NotResource"]) ]) # http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/protect-stack-resources.html#stack-policy-reference policy_json_spec = lambda: sb.set_options(Statement=sb.listof( policy_set_options( Effect=sb.string_choice_spec(choices=["Deny", "Allow"]), Action=sb.optional_spec( sb.listof( sb.string_choice_spec(choices=[ "Update:Modify", "Update:Replace", "Update:Delete", "Update:*" ]))), NotAction=sb.optional_spec( sb.listof( sb.string_choice_spec(choices=[ "Update:Modify", "Update:Replace", "Update:Delete", "Update:*" ]))), Principal=sb.valid_string_spec(validators.regexed("^\*$")), Resource=sb.optional_spec( sb.listof(
def normalise_filled(self, meta, val): val = sb.string_choice_spec(list(palettes)).normalise(meta, val) return palettes[val]
def stack_spec(self): """Spec for each stack""" return create_spec( stack_objs.Stack, validators.deprecated_key( "url_checker", "Use ``confirm_deployment.url_checker1``"), validators.deprecated_key( "deploys_s3_path", "Use ``confirm_deployment.deploys_s3_path``"), validators.deprecated_key( "sns_confirmation", "Use ``confirm_deployment.sns_confirmation``"), validators.deprecated_key("autoscaling_group_id", "Use ``auto_scaling_group_name``"), validators.deprecated_key( "instance_count_limit", "Use ``scaling_options.instance_count_limit``"), bespin=any_spec(), name=formatted(defaulted(string_spec(), "{_key_name_1}"), formatter=MergedOptionStringFormatter), key_name=formatted(overridden("{_key_name_1}"), formatter=MergedOptionStringFormatter), stack_name=formatted(defaulted(string_spec(), "{_key_name_1}"), formatter=MergedOptionStringFormatter), environment=formatted(overridden("{environment}"), formatter=MergedOptionStringFormatter), env=listof(stack_specs.env_spec(), expect=stack_objs.EnvironmentVariable), build_env=listof(stack_specs.env_spec(), expect=stack_objs.EnvironmentVariable), stack_name_env=listof(stack_specs.env_spec(), expect=stack_objs.EnvironmentVariable), tags=self.tags_spec, termination_protection=defaulted(boolean(), False), stack_json=valid_stack_json( default="{config_root}/{_key_name_1}.json"), stack_yaml=valid_stack_yaml( default="{config_root}/{_key_name_1}.yaml"), params_json=valid_params_json( default="{config_root}/{environment}/{_key_name_1}-params.json" ), params_yaml=valid_params_yaml( default="{config_root}/{environment}/{_key_name_1}-params.yaml" ), stack_policy=valid_policy_json( default="{config_root}/{_key_name_1}-policy.json"), role_name=formatted(string_spec(), formatter=MergedOptionStringFormatter), build_first=listof( formatted(string_spec(), formatter=MergedOptionStringFormatter)), build_after=listof( formatted(string_spec(), formatter=MergedOptionStringFormatter)), build_timeout=defaulted(integer_spec(), 1200), ignore_deps=defaulted(boolean(), False), vars=delayed( dictof(string_spec(), stack_specs.var_spec(), nested=True)), skip_update_if_equivalent=listof(stack_specs.skipper_spec()), suspend_actions=defaulted(boolean(), False), auto_scaling_group_name=optional_spec( formatted(string_spec(), formatter=MergedOptionStringFormatter)), artifact_retention_after_deployment=defaulted(boolean(), False), command=optional_spec(string_spec()), netscaler=optional_spec(self.netscaler_spec), notify_stackdriver=defaulted(boolean(), False), stackdriver=optional_spec( create_spec( stack_objs.Stackdriver, api_key=required( formatted(string_spec(), formatter=MergedOptionStringFormatter)), deployment_version=defaulted( formatted(string_spec(), formatter=MergedOptionStringFormatter), "<version>"))), dns=optional_spec( stack_specs.dns_spec( create_spec( stack_objs.DNS, vars=dictof( string_spec(), formatted(string_spec(), formatter=MergedOptionStringFormatter), nested=True), providers=dictof(string_spec(), stack_specs.dns_provider_spec()), sites=delayed( dictof(string_spec(), stack_specs.dns_site_spec()))))), scaling_options=create_spec( ScalingOptions, highest_min=defaulted(integer_spec(), 2), instance_count_limit=defaulted(integer_spec(), 10)), artifacts=container_spec( artifact_objs.ArtifactCollection, dictof( string_spec(), create_spec( artifact_objs.Artifact, not_created_here=defaulted(boolean(), False), compression_type=string_choice_spec(["gz", "xz"]), history_length=integer_spec(), cleanup_prefix=optional_spec(string_spec()), upload_to=formatted( string_spec(), formatter=MergedOptionStringFormatter), commands=listof(stack_specs.artifact_command_spec(), expect=artifact_objs.ArtifactCommand), paths=listof(stack_specs.artifact_path_spec(), expect=artifact_objs.ArtifactPath), files=listof( create_spec( artifact_objs.ArtifactFile, validators.has_either(["content", "task"]), content=optional_spec( formatted( string_spec(), formatter=MergedOptionStringFormatter) ), task=optional_spec( formatted( string_spec(), formatter=MergedOptionStringFormatter) ), path=formatted( string_spec(), formatter=MergedOptionStringFormatter), task_runner=formatted( always_same_spec("{task_runner}"), formatter=MergedOptionStringFormatter))))) ), newrelic=optional_spec( create_spec( stack_objs.NewRelic, api_key=required( formatted(string_spec(), formatter=MergedOptionStringFormatter)), account_id=required( formatted(string_spec(), formatter=MergedOptionStringFormatter)), application_id=required( formatted(string_spec(), formatter=MergedOptionStringFormatter)), env=listof(stack_specs.env_spec(), expect=stack_objs.EnvironmentVariable), deployed_version=required( formatted(string_spec(), formatter=MergedOptionStringFormatter)))), downtimer_options=optional_spec( dictof( valid_string_spec(valid_alerting_system()), create_spec( stack_objs.DowntimerOptions, hosts=listof( formatted( string_spec(), formatter=MergedOptionStringFormatter))))), alerting_systems=optional_spec( dictof(string_spec(), self.alerting_system_spec)), ssh=optional_spec( create_spec( stack_objs.SSH, validators.deprecated_key( "autoscaling_group_id", "Use ``auto_scaling_group_name``"), user=required( formatted(string_spec(), formatter=MergedOptionStringFormatter)), bastion=optional_spec( formatted(string_spec(), formatter=MergedOptionStringFormatter)), bastion_user=required( formatted(string_spec(), formatter=MergedOptionStringFormatter)), bastion_key_location=optional_spec( formatted(string_spec(), formatter=MergedOptionStringFormatter)), instance_key_location=optional_spec( formatted(string_spec(), formatter=MergedOptionStringFormatter)), address=optional_spec( formatted(string_spec(), formatter=MergedOptionStringFormatter)), instance=optional_spec( listof( formatted(string_spec(), formatter=MergedOptionStringFormatter))), auto_scaling_group_name=optional_spec( formatted(string_spec(), formatter=MergedOptionStringFormatter)), bastion_key_path=formatted( defaulted( string_spec(), "{config_root}/{environment}/bastion_ssh_key.pem"), formatter=MergedOptionStringFormatter), instance_key_path=formatted( defaulted(string_spec(), "{config_root}/{environment}/ssh_key.pem"), formatter=MergedOptionStringFormatter), storage_type=formatted( defaulted(string_choice_spec(["url", "rattic"]), "url"), formatter=MergedOptionStringFormatter), storage_host=optional_spec( formatted(string_spec(), formatter=MergedOptionStringFormatter)))), confirm_deployment=optional_spec(self.confirm_deployment_spec))