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 harpoon_spec(self): """Spec for harpoon options""" formatted_string = formatted(string_spec(), MergedOptionStringFormatter, expected_type=six.string_types) formatted_boolean = formatted(boolean(), MergedOptionStringFormatter, expected_type=bool) return create_spec( Harpoon, config=file_spec(), extra=defaulted(formatted_string, ""), debug=defaulted(boolean(), False), chosen_task=defaulted(formatted_string, "list_tasks"), chosen_image=defaulted(formatted_string, ""), flat=defaulted(formatted_boolean, False), no_cleanup=defaulted(formatted_boolean, False), interactive=defaulted(formatted_boolean, True), silent_build=defaulted(formatted_boolean, False), keep_replaced=defaulted(formatted_boolean, False), ignore_missing=defaulted(formatted_boolean, False), no_intervention=defaulted(formatted_boolean, False), intervene_afterwards=defaulted(formatted_boolean, False), do_push=defaulted(formatted_boolean, False), only_pushable=defaulted(formatted_boolean, False), docker_context=any_spec(), docker_context_maker=any_spec(), stdout=defaulted(any_spec(), sys.stdout), tty_stdout=defaulted(any_spec(), lambda: sys.stdout), tty_stderr=defaulted(any_spec(), lambda: sys.stderr))
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) gateway_name = meta.key_names()['_key_name_0'] gateway_location = formatted_string().normalise( meta.at('location'), val.get('location', '')) return sb.create_spec( Gateway, name=sb.overridden(gateway_name), location=sb.required(formatted_string()), stages=sb.listof(formatted_string()), api_keys=sb.listof(api_key_spec()), domain_names=sb.dictof(sb.string_spec(), custom_domain_name_spec(gateway_location)), resources=sb.dictof(sb.string_spec(), gateway_resource_spec())).normalise(meta, val)
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_or_int_as_string_spec(), MergedOptionStringFormatter, expected_type=six.string_types) key_name = meta.key_names()['_key_name_0'] key = sb.create_spec(EncryptionKey , name = sb.overridden(key_name) , location = sb.required(formatted_string) , description = formatted_string , grant = sb.listof(grant_statement_spec('key', key_name)) , admin_users = sb.listof(sb.any_spec()) , permission = sb.listof(sb.dictionary_spec()) , no_root_access = sb.defaulted(sb.boolean(), False) ).normalise(meta, val) statements = key.permission if not key.no_root_access: statements.append({"principal": {"iam": "root"}, "action": "kms:*", "resource": "*", "Sid": ""}) if key.admin_users: for admin_user in key.admin_users: statements.append({"principal": admin_user, "action": "kms:*", "resource": { "kms": "__self__" }, "Sid": ""}) key.policy = sb.container_spec(Document, sb.listof(resource_policy_statement_spec('key', key_name))).normalise(meta.at("admin_users"), statements) return key
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_or_int_as_string_spec(), MergedOptionStringFormatter, expected_type=six.string_types ) key_name = meta.key_names()["_key_name_0"] key = sb.create_spec( EncryptionKey, name=sb.overridden(key_name), location=sb.required(formatted_string), description=formatted_string, grant=sb.listof(grant_statement_spec("key", key_name)), admin_users=sb.listof(sb.any_spec()), ).normalise(meta, val) statements = [{"principal": {"iam": "root"}, "action": "kms:*", "resource": "*", "Sid": ""}] if key.admin_users: for admin_user in key.admin_users: statements.append( {"principal": admin_user, "action": "kms:*", "resource": {"kms": "__self__"}, "Sid": ""} ) key.policy = sb.container_spec(Document, sb.listof(resource_policy_statement_spec("key", key_name))).normalise( meta.at("admin_users"), statements ) return key
def reference_resolver_register_spec(self): """ Make a ReferenceResolerRegister object .. autoclass:: photons_app.option_spec.photons_app_spec.ReferenceResolerRegister """ return sb.create_spec(ReferenceResolerRegister)
def netscaler_spec(self): class to_boolean(Spec): def setup(self, spec): self.spec = spec def normalise_either(self, meta, val): val = self.spec.normalise(meta, val) if type(val) is bool: return val if val == 'False': return False elif val == 'True': return True raise BadConfiguration("Expected a boolean", got=val, meta=meta) return create_spec(netscaler_specs.NetScaler , host = required(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , dry_run = to_boolean(formatted(overridden("{bespin.dry_run}"), formatter=MergedOptionStringFormatter)) , username = required(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , configuration_username = optional_spec(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , password = delayed(required(formatted(string_spec(), formatter=MergedOptionStringFormatter))) , configuration_password = optional_spec(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , verify_ssl = defaulted(boolean(), True) , nitro_api_version = defaulted(formatted(string_spec(), formatter=MergedOptionStringFormatter), "v1") , configuration = optional_spec(netscaler_specs.configuration_spec()) , syncable_environments = optional_spec(listof(valid_environment_spec())) )
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_or_int_as_string_spec(), MergedOptionStringFormatter, expected_type=six.string_types) function_name = meta.key_names()['_key_name_0'] val = sb.create_spec(Lambda , name = sb.overridden(function_name) , role = sb.required(only_one_spec(resource_spec("lambda", function_name, only=["iam"]))) , code = sb.required(function_code_spec()) , handler = function_handler_spec() , timeout = sb.integer_spec() , runtime = sb.required(formatted_string) , location = sb.required(formatted_string) , description = formatted_string , sample_event = sb.defaulted(sb.or_spec(formatted_dictionary(), sb.string_spec()), "") , desired_output_for_test = sb.defaulted(sb.or_spec(formatted_dictionary(), sb.string_spec()), "") , memory_size = sb.defaulted(divisible_by_spec(64), 128) ).normalise(meta, val) # Hack to make sample_event and desired_output_for_test not appear as a MergedOptions for key in ('sample_event', 'desired_output_for_test'): if isinstance(val[key], MergedOptions): v = val[key].as_dict() class Arbritrary(dictobj): fields = list(v.keys()) val[key] = Arbritrary(**v) return val
def harpoon_spec(self): """Spec for harpoon options""" formatted_string = formatted(string_spec(), MergedOptionStringFormatter, expected_type=six.string_types) formatted_boolean = formatted(boolean(), MergedOptionStringFormatter, expected_type=bool) return create_spec( Harpoon, config=file_spec(), extra=defaulted(formatted_string, ""), debug=defaulted(boolean(), False), chosen_task=defaulted(formatted_string, "list_tasks"), chosen_image=defaulted(formatted_string, ""), flat=defaulted(formatted_boolean, False), no_cleanup=defaulted(formatted_boolean, False), interactive=defaulted(formatted_boolean, True), silent_build=defaulted(formatted_boolean, False), keep_replaced=defaulted(formatted_boolean, False), ignore_missing=defaulted(formatted_boolean, False), no_intervention=defaulted(formatted_boolean, False), intervene_afterwards=defaulted(formatted_boolean, False), do_push=defaulted(formatted_boolean, False), only_pushable=defaulted(formatted_boolean, False), docker_context=any_spec(), docker_context_maker=any_spec(), stdout=defaulted(any_spec(), sys.stdout), tty_stdout=defaulted(any_spec(), lambda: sys.stdout), tty_stderr=defaulted(any_spec(), lambda: sys.stderr), )
def url_checker_spec(self): return create_spec(deployment_check.UrlChecker , check_url = required(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , endpoint = required(delayed(stack_specs.var_spec())) , expect = required(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , timeout_after = defaulted(integer_spec(), 600) )
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): 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, expected_type=six.string_types) role_name = meta.key_names()['_key_name_0'] original_permission = sb.listof(permission_dict()).normalise(meta.at("permission"), NotSpecified if "permission" not in val else val["permission"]) deny_permission = sb.listof(permission_dict(effect='Deny')).normalise(meta.at("deny_permission"), NotSpecified if "deny_permission" not in val else val["deny_permission"]) allow_permission = sb.listof(permission_dict(effect='Allow')).normalise(meta.at("allow_permission"), NotSpecified if "allow_permission" not in val else val["allow_permission"]) allow_to_assume_me = sb.listof(trust_dict("principal")).normalise(meta.at("allow_to_assume_me"), val.get("allow_to_assume_me", NotSpecified)) disallow_to_assume_me = sb.listof(trust_dict("notprincipal")).normalise(meta.at("disallow_to_assume_me"), val.get("disallow_to_assume_me", NotSpecified)) val = val.wrapped() val['trust'] = allow_to_assume_me + disallow_to_assume_me val['permission'] = original_permission + deny_permission + allow_permission return sb.create_spec(Role , name = sb.overridden(role_name) , description = formatted_string , trust = sb.container_spec(Document, sb.listof(trust_statement_spec('role', role_name))) , permission = sb.container_spec(Document, sb.listof(permission_statement_spec('role', role_name))) , make_instance_profile = sb.defaulted(sb.boolean(), False) ).normalise(meta, val)
def environment_spec(self): """Spec for each environment""" return create_spec(Environment , account_id = required(or_spec(string_spec(), valid_string_spec(validators.regexed("\d+")))) , region = defaulted(string_spec(), "ap-southeast-2") , vars = dictionary_spec() )
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): result = sb.create_spec(LambdaPostMethod , function = formatted_string() , location = formatted_string() , account = sb.optional_spec(formatted_string()) , require_api_key = sb.defaulted(sb.boolean(), False) , mapping = sb.defaulted(mapping_spec(), Mapping("application/json", "$input.json('$')")) ).normalise(meta, val) function = result.function location = None if result.location is not NotSpecified and location is not None: raise BadSpecValue("Please don't specify a defined lambda function and location at the same time", meta=meta) if not isinstance(function, six.string_types): location = function.location function = function.name if location is None and result.location is NotSpecified: raise BadSpecValue("Location is a required key!", meta=meta) result.function = function result.location = location return result
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_or_int_as_string_spec(), MergedOptionStringFormatter, expected_type=six.string_types) bucket_name = meta.key_names()['_key_name_0'] original_permission = sb.listof(resource_policy_dict()).normalise(meta.at("permission"), NotSpecified if "permission" not in val else val["permission"]) deny_permission = sb.listof(resource_policy_dict(effect='Deny')).normalise(meta.at("deny_permission"), NotSpecified if "deny_permission" not in val else val["deny_permission"]) allow_permission = sb.listof(resource_policy_dict(effect='Allow')).normalise(meta.at("allow_permission"), NotSpecified if "allow_permission" not in val else val["allow_permission"]) # require_mfa_to_delete is an alias for this permission if val.get("require_mfa_to_delete") is True: delete_policy = {"action": "s3:DeleteBucket", "resource": { "s3": "__self__" }, "Condition": { "Bool": { "aws:MultiFactorAuthPresent": True } } } normalised_delete_policy = resource_policy_dict(effect='Allow').normalise(meta.at("require_mfa_to_delete"), delete_policy) allow_permission.append(normalised_delete_policy) val = val.wrapped() val['permission'] = original_permission + deny_permission + allow_permission return sb.create_spec(Bucket , acl = sb.defaulted(sb.match_spec((six.string_types, canned_acl_spec()), (dict, acl_statement_spec('acl', 'acl'))), None) , name = sb.overridden(bucket_name) , location = sb.defaulted(formatted_string, None) , permission = sb.container_spec(Document, sb.listof(resource_policy_statement_spec('bucket', bucket_name))) , tags = sb.dictof(sb.string_spec(), formatted_string) , website = sb.defaulted(website_statement_spec("website", "website"), None) , logging = sb.defaulted(logging_statement_spec("logging", "logging"), None) , lifecycle = sb.defaulted(sb.listof(lifecycle_statement_spec("lifecycle", "lifecycle")), None) ).normalise(meta, val)
def bespin_spec(self): """Spec for bespin options""" formatted_string = formatted(string_spec(), MergedOptionStringFormatter, expected_type=six.string_types) formatted_boolean = formatted(boolean(), MergedOptionStringFormatter, expected_type=bool) return create_spec(Bespin , validators.deprecated_key("region", "Please use ``environments.<env>.region``") , config = file_spec() , configuration = any_spec() , assume_role = optional_spec(string_spec()) , dry_run = defaulted(boolean(), False) , flat = defaulted(boolean(), False) , environment = optional_spec(string_spec()) , no_assume_role = defaulted(formatted_boolean, False) , chosen_task = defaulted(formatted_string, "list_tasks") , chosen_stack = defaulted(formatted_string, "") , chosen_artifact = defaulted(formatted_string, "") , extra_imports = listof(imports.import_spec()) )
def bespin_spec(self): """Spec for bespin options""" formatted_string = formatted(string_spec(), MergedOptionStringFormatter, expected_type=six.string_types) formatted_boolean = formatted(boolean(), MergedOptionStringFormatter, expected_type=bool) return create_spec(Bespin, validators.deprecated_key( "region", "Please use ``environments.<env>.region``"), config=file_spec(), configuration=any_spec(), assume_role=optional_spec(string_spec()), extra=defaulted(string_spec(), ""), dry_run=defaulted(boolean(), False), flat=defaulted(boolean(), False), environment=optional_spec(string_spec()), no_assume_role=defaulted(formatted_boolean, False), chosen_task=defaulted(formatted_string, "list_tasks"), chosen_stack=defaulted(formatted_string, ""), chosen_artifact=defaulted(formatted_string, ""), extra_imports=listof(imports.import_spec()))
def ultradns_provider_spec(self): return sb.create_spec(UltraDNSProvider , name = sb.formatted(sb.overridden("{_key_name_1}"), formatter=MergedOptionStringFormatter) , provider_type = sb.required(sb.string_spec()) , username = sb.required(formatted_string) , password = sb.required(formatted_string) )
def confirm_deployment_spec(self): return create_spec(deployment_check.ConfirmDeployment , deploys_s3_path = optional_spec(listof(stack_specs.s3_address())) , zero_instances_is_ok = defaulted(boolean(), False) , auto_scaling_group_name = optional_spec(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , url_checker = optional_spec(self.url_checker_spec) , sns_confirmation = optional_spec(create_spec(deployment_check.SNSConfirmation , validators.deprecated_key("auto_scaling_group_id", "Use ``confirm_deployment.auto_scaling_group_name``") , validators.deprecated_key("env", "Use ``stack.<stack>.env`` instead``") , timeout = defaulted(integer_spec(), 300) , version_message = required(formatted(string_spec(), formatter=MergedOptionStringFormatter)) , deployment_queue = required(formatted(string_spec(), formatter=MergedOptionStringFormatter)) )) )
def ultradns_provider_spec(self): return sb.create_spec(UltraDNSProvider, name=sb.formatted( sb.overridden("{_key_name_1}"), formatter=MergedOptionStringFormatter), provider_type=sb.required(sb.string_spec()), username=sb.required(formatted_string), password=sb.required(formatted_string))
def environment_spec(self): """Spec for each environment""" return create_spec(stack_objs.Environment , account_id = required(or_spec(valid_string_spec(validators.regexed("\d+")), integer_spec())) , region = defaulted(string_spec(), "ap-southeast-2") , vars = dictionary_spec() , tags = self.tags_spec )
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, expected_type=six.string_types) role_name = meta.key_names()['_key_name_0'] original_permission = sb.listof(permission_dict()).normalise( meta.at("permission"), NotSpecified if "permission" not in val else val["permission"]) deny_permission = sb.listof(permission_dict(effect='Deny')).normalise( meta.at("deny_permission"), NotSpecified if "deny_permission" not in val else val["deny_permission"]) allow_permission = sb.listof( permission_dict(effect='Allow')).normalise( meta.at("allow_permission"), NotSpecified if "allow_permission" not in val else val["allow_permission"]) allow_to_assume_me = sb.listof(trust_dict("principal")).normalise( meta.at("allow_to_assume_me"), val.get("allow_to_assume_me", NotSpecified)) disallow_to_assume_me = sb.listof( trust_dict("notprincipal")).normalise( meta.at("disallow_to_assume_me"), val.get("disallow_to_assume_me", NotSpecified)) if not allow_to_assume_me and not disallow_to_assume_me: raise BadSpecValue( "Roles must have either allow_to_assume_me or disallow_to_assume_me specified", meta=meta) val = val.wrapped() val['trust'] = allow_to_assume_me + disallow_to_assume_me val['permission'] = original_permission + deny_permission + allow_permission return sb.create_spec( Role, name=sb.overridden(role_name), description=formatted_string, attached_policies=sb.listof(formatted_string), trust=sb.container_spec( Document, sb.listof(trust_statement_spec('role', role_name))), permission=sb.container_spec( Document, sb.listof(permission_statement_spec('role', role_name))), make_instance_profile=sb.defaulted(sb.boolean(), False)).normalise(meta, val)
def target_register_spec(self): """ Make a TargetRegister object .. autoclass:: photons_app.option_spec.photons_app_spec.TargetRegister """ return sb.create_spec(TargetRegister, collector=sb.formatted( sb.overridden("{collector}"), formatter=MergedOptionStringFormatter))
def normalise(self, meta, val): if isinstance(val, six.string_types): val = formatted_string().normalise(meta, val) return sb.create_spec(Certificate, name=sb.required(formatted_string()), body=sb.required(secret_spec()), key=sb.required(secret_spec()), chain=sb.required(secret_spec())).normalise( meta, val)
def normalise(self, meta, val): if isinstance(val, six.string_types): val = formatted_string().normalise(meta, val) return sb.create_spec(Certificate , name = sb.required(formatted_string()) , body = sb.required(secret_spec()) , key = sb.required(secret_spec()) , chain = sb.required(secret_spec()) ).normalise(meta, val)
def make_spec(self, meta): """ Assume self.kls has a fields dictionary of fields = {name: (description, options)} or fields = {name: options} Where options may be: * A callable object to a spec or Field * A spec * A Field If it's a Field, we create a spec from that Finally we create a create_spec with all the fields """ kwargs = {} errors = [] if not hasattr(self.kls, "fields"): raise BadSpec("No fields on the class!", kls=self.kls) for name, options in sorted(self.kls.fields.items()): if type(options) in (tuple, list): if len(options) == 2: options = options[1] elif len(options) == 1: options = options[0] if not options or isinstance(options, six.string_types): errors.append(BadSpec("No spec found for option", option=name, meta=meta.at(name))) if callable(options): options = options() spec = None if isinstance(options, Field): try: spec = options.make_spec(meta.at(name), self.formatter) except BadSpec as error: errors.append(error) else: spec = options # And set our field kwargs[name] = spec if errors: raise BadSpec(_errors=errors) return create_spec(self.create_kls, **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 ultradns_site_spec(self, this): formatted_string = sb.formatted(sb.string_spec(), formatter=MergedOptionStringFormatter) return sb.create_spec(UltraDNSSite , name = sb.formatted(sb.overridden("{_key_name_1}"), formatter=MergedOptionStringFormatter) , ttl = sb.optional_spec(sb.integer_spec()) , provider = sb.any_spec() , record_type = sb.required(formatted_string) , zone = sb.required(formatted_string) , domain = sb.required(formatted_string) , environments = sb.required(self.dns_environment_spec(this)) )
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(self, meta, val): from harpoon.option_spec.harpoon_specs import HarpoonSpec formatted_string = sb.formatted(sb.string_spec(), formatter=MergedOptionStringFormatter) val = sb.apply_validators(meta, val, [validators.either_keys(["context"], ["content"], ["get"], ["formatted"])]) if "get" in val: val = sb.create_spec(CommandAddExtra , get = sb.required(sb.listof(formatted_string)) , prefix = sb.optional_spec(sb.string_spec()) ).normalise(meta, val) if "context" in val: val = sb.create_spec(CommandContextAdd , validators.deprecated_key("mtime", "Since docker 1.8, timestamps no longer invalidate the docker layer cache") , dest = sb.required(formatted_string) , context = sb.required(HarpoonSpec().context_spec) ).normalise(meta, val) if "formatted" in val: val = sb.create_spec(CommandContentAdd , validators.deprecated_key("mtime", "Since docker 1.8, timestamps no longer invalidate the docker layer cache") , dest = sb.required(formatted_string) , content = sb.overridden(sb.NotSpecified) , formatted = sb.container_spec(CommandContentAddString, formatted_string) ).normalise(meta, val) if "content" in val: val = sb.create_spec(CommandContentAdd , validators.deprecated_key("mtime", "Since docker 1.8, timestamps no longer invalidate the docker layer cache") , dest = sb.required(formatted_string) , content = sb.match_spec( (six.string_types, sb.container_spec(CommandContentAddString, sb.string_spec())) , fallback = complex_ADD_from_image_spec() ) ).normalise(meta, val) return list(val.commands(meta))
def password_spec(self): formatted_string = formatted(string_spec(), formatter=MergedOptionStringFormatter) return create_spec(stack_objs.Password , name = formatted(overridden("{_key_name_1}"), formatter=MergedOptionStringFormatter) , bespin = formatted(overridden("{bespin}"), formatter=MergedOptionStringFormatter) , KMSMasterKey = required(formatted_string) , encryption_context = optional_spec(dictionary_spec()) , grant_tokens = optional_spec(listof(formatted_string)) , crypto_text = required(formatted_string) , vars = dictionary_spec() )
def normalise(self, meta, val): formatted_string = sb.formatted(sb.string_spec(), formatter=MergedOptionStringFormatter) img, conf = complex_from_image_spec().normalise(meta.at("image"), val["image"]) val["conf"] = conf return sb.create_spec(CommandContentAddDict , image = sb.overridden(img) , conf = sb.any_spec() , path = formatted_string , images = sb.overridden(meta.everything.get("images", [])) , docker_api = sb.overridden(meta.everything["harpoon"].docker_api) ).normalise(meta, val)
def ultradns_site_spec(self, this): formatted_string = sb.formatted(sb.string_spec(), formatter=MergedOptionStringFormatter) return sb.create_spec( UltraDNSSite, name=sb.formatted(sb.overridden("{_key_name_1}"), formatter=MergedOptionStringFormatter), ttl=sb.optional_spec(sb.integer_spec()), provider=sb.any_spec(), record_type=sb.required(formatted_string), zone=sb.required(formatted_string), domain=sb.required(formatted_string), environments=sb.required(self.dns_environment_spec(this)))
def aws_syncr_spec(self): """Spec for aws_syncr options""" formatted_string = formatted(string_spec(), MergedOptionStringFormatter, expected_type=six.string_types) return create_spec(AwsSyncr , extra = defaulted(formatted_string, "") , stage = defaulted(formatted_string, "") , debug = defaulted(boolean(), False) , dry_run = defaulted(boolean(), False) , location = defaulted(formatted_string, "ap-southeast-2") , artifact = formatted_string , environment = formatted_string , config_folder = directory_spec() )
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_or_int_as_string_spec(), MergedOptionStringFormatter, expected_type=six.string_types) function_name = meta.key_names()['_key_name_0'] val = sb.create_spec(Lambda, name=sb.overridden(function_name), role=sb.required( only_one_spec( resource_spec("lambda", function_name, only=["iam"]))), code=sb.required(function_code_spec()), handler=function_handler_spec(), timeout=sb.integer_spec(), runtime=sb.required(formatted_string), location=sb.required(formatted_string), description=formatted_string, sample_event=sb.defaulted( sb.or_spec(formatted_dictionary(), sb.string_spec()), ""), desired_output_for_test=sb.defaulted( sb.or_spec(formatted_dictionary(), sb.string_spec()), ""), memory_size=sb.defaulted(divisible_by_spec(64), 128)).normalise( meta, val) # Hack to make sample_event and desired_output_for_test not appear as a MergedOptions for key in ('sample_event', 'desired_output_for_test'): if isinstance(val[key], MergedOptions): v = val[key].as_dict() class Arbritrary(dictobj): fields = list(v.keys()) val[key] = Arbritrary(**v) return val
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 context_spec(self): """Spec for specifying context options""" from harpoon.option_spec import image_objs return dict_from_bool_spec(lambda meta, val: {"enabled": val} , create_spec(image_objs.Context , include = listof(string_spec()) , exclude = listof(string_spec()) , enabled = defaulted(boolean(), True) , parent_dir = directory_spec(formatted(defaulted(string_spec(), "{config_root}"), formatter=MergedOptionStringFormatter)) , use_gitignore = defaulted(boolean(), False) , use_git_timestamps = defaulted(or_spec(boolean(), listof(string_spec())), False) ) )
def normalise(self, meta, val): from harpoon.option_spec.harpoon_specs import HarpoonSpec formatted_string = sb.formatted(sb.string_spec(), formatter=MergedOptionStringFormatter) val = sb.apply_validators(meta, val, [validators.either_keys(["context"], ["content"], ["get"], ["formatted"])]) if "get" in val: val = sb.create_spec(CommandAddExtra , get = sb.required(sb.listof(formatted_string)) , prefix = sb.optional_spec(sb.string_spec()) ).normalise(meta, val) if "context" in val: val = sb.create_spec(CommandContextAdd , dest = sb.required(formatted_string) , mtime = sb.optional_spec(sb.integer_spec()) , context = sb.required(HarpoonSpec().context_spec) ).normalise(meta, val) if "formatted" in val: val = sb.create_spec(CommandContentAdd , dest = sb.required(formatted_string) , mtime = sb.optional_spec(sb.integer_spec()) , content = sb.overridden(sb.NotSpecified) , formatted = sb.container_spec(CommandContentAddString, formatted_string) ).normalise(meta, val) if "content" in val: val = sb.create_spec(CommandContentAdd , dest = sb.required(formatted_string) , mtime = sb.optional_spec(sb.integer_spec()) , content = sb.match_spec( (six.string_types, sb.container_spec(CommandContentAddString, sb.string_spec())) , fallback = complex_ADD_from_image_spec() ) ).normalise(meta, val) return list(val.commands(meta))
def normalise(self, meta, val): name = meta.key_names()["_key_name_0"] result = sb.create_spec(DomainName , name = sb.overridden(name) , gateway_location = sb.overridden(self.gateway_location) , zone = formatted_string() , stage = formatted_string() , base_path = sb.defaulted(formatted_string(), "(none)") , certificate = sb.required(certificate_spec()) ).normalise(meta, val) while result.zone and result.zone.endswith("."): result.zone = result.zone[:-1] return result
def aws_syncr_spec(self): """Spec for aws_syncr options""" formatted_string = formatted(string_spec(), MergedOptionStringFormatter, expected_type=six.string_types) return create_spec(AwsSyncr, extra=defaulted(formatted_string, ""), stage=defaulted(formatted_string, ""), debug=defaulted(boolean(), False), dry_run=defaulted(boolean(), False), location=defaulted(formatted_string, "ap-southeast-2"), artifact=formatted_string, environment=formatted_string, config_folder=directory_spec())
def normalise(self, meta, val): name = meta.key_names()["_key_name_0"] result = sb.create_spec( DomainName, name=sb.overridden(name), gateway_location=sb.overridden(self.gateway_location), zone=formatted_string(), stage=formatted_string(), base_path=sb.defaulted(formatted_string(), "(none)"), certificate=sb.required(certificate_spec())).normalise(meta, val) while result.zone and result.zone.endswith("."): result.zone = result.zone[:-1] return result
def context_spec(self): """Spec for specifying context options""" from harpoon.option_spec import image_objs return dict_from_bool_spec( lambda meta, val: {"enabled": val}, create_spec(image_objs.Context, include=listof(string_spec()), exclude=listof(string_spec()), enabled=defaulted(boolean(), True), parent_dir=directory_spec( formatted(defaulted(string_spec(), "{config_root}"), formatter=MergedOptionStringFormatter)), use_gitignore=defaulted(boolean(), False), use_git_timestamps=defaulted( or_spec(boolean(), listof(string_spec())), False)))
def wait_condition_spec(self): """Spec for a wait_condition block""" from harpoon.option_spec import image_objs formatted_string = formatted(string_spec(), formatter=MergedOptionStringFormatter) return create_spec(image_objs.WaitCondition , harpoon = formatted(overridden("{harpoon}"), formatter=MergedOptionStringFormatter) , timeout = defaulted(integer_spec(), 300) , wait_between_attempts = defaulted(float_spec(), 5) , greps = optional_spec(dictof(formatted_string, formatted_string)) , command = optional_spec(listof(formatted_string)) , port_open = optional_spec(listof(integer_spec())) , file_value = optional_spec(dictof(formatted_string, formatted_string)) , curl_result = optional_spec(dictof(formatted_string, formatted_string)) , file_exists = optional_spec(listof(formatted_string)) )
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(self, meta, val): result = sb.create_spec( LambdaMethod, http_method=sb.overridden(self.method), resource_name=sb.overridden(self.resource_name), function=formatted_string(), location=formatted_string(), account=sb.optional_spec(formatted_string()), require_api_key=sb.defaulted(sb.boolean(), False), request_mapping=sb.defaulted(mapping_spec(), Mapping("application/json", "")), mapping=sb.defaulted( mapping_spec(), Mapping("application/json", "$input.json('$')")), sample_event=sb.or_spec(formatted_dictionary(), sb.string_spec()), desired_output_for_test=sb.or_spec(formatted_dictionary(), sb.string_spec())).normalise( meta, val) for key in ('sample_event', 'desired_output_for_test'): if isinstance(result[key], six.string_types): v = result[key] if v.startswith("{") and v.endswith("}"): v = sb.formatted( sb.string_spec(), formatter=MergedOptionStringFormatter).normalise( meta.at(key), v) result[key] = v function = result.function location = None if result.location is not NotSpecified and location is not None: raise BadSpecValue( "Please don't specify a defined lambda function and location at the same time", meta=meta) if not isinstance(function, six.string_types): location = function.location function = function.name if location is None and result.location is NotSpecified: raise BadSpecValue("Location is a required key!", meta=meta) result.function = function result.location = location return result
def context_spec(self): """Spec for specifying context options""" from harpoon.option_spec import image_objs return dict_from_bool_spec(lambda meta, val: {"enabled": val} , create_spec(image_objs.Context , validators.deprecated_key("use_git_timestamps", "Since docker 1.8, timestamps no longer invalidate the docker layer cache") , include = listof(string_spec()) , exclude = listof(string_spec()) , enabled = defaulted(boolean(), True) , find_options = string_spec() , parent_dir = directory_spec(formatted(defaulted(string_spec(), "{config_root}"), formatter=MergedOptionStringFormatter)) , use_gitignore = defaulted(boolean(), False) , ignore_find_errors = defaulted(boolean(), False) ) )
def normalise(self, meta, val): from harpoon.option_spec.harpoon_specs import HarpoonSpec from harpoon.option_spec.image_objs import Image formatted_string = sb.formatted(sb.or_spec(sb.string_spec(), sb.typed(Image)), formatter=MergedOptionStringFormatter) img = val["conf"] = sb.set_options(image = formatted_string).normalise(meta, val)["image"] if isinstance(img, six.string_types): val["conf"] = HarpoonSpec().image_spec.normalise(meta.at("image"), {"commands": ["FROM {0}".format(img)]}) val["conf"].image_name = img return sb.create_spec(CommandContentAddDict , image = sb.overridden(img) , conf = sb.any_spec() , path = formatted_string , images = sb.overridden(meta.everything.get("images", [])) , docker_context = sb.overridden(meta.everything["harpoon"].docker_context) ).normalise(meta, val)
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): return sb.create_spec(MockMethod , http_method = sb.overridden(self.method) , resource_name = sb.overridden(self.resource_name) , request_mapping = sb.defaulted(mapping_spec(), Mapping("application/json", '{"statusCode": 200}')) , mapping = mapping_spec() , require_api_key = sb.defaulted(sb.boolean(), False) , sample_event = sb.or_spec(sb.dictionary_spec(), sb.string_spec()) , desired_output_for_test = sb.or_spec(sb.dictionary_spec(), sb.string_spec()) ).normalise(meta, val) for key in ('sample_event', 'desired_output_for_test'): if isinstance(result[key], six.string_types): v = result[key] if v.startswith("{") and v.endswith("}"): v = sb.formatted(sb.string_spec(), formatter=MergedOptionStringFormatter).normalise(meta.at(key), v) result[key] = v
def wait_condition_spec(self): """Spec for a wait_condition block""" from harpoon.option_spec import image_objs formatted_string = formatted(string_spec(), formatter=MergedOptionStringFormatter) return create_spec( image_objs.WaitCondition, harpoon=formatted(overridden("{harpoon}"), formatter=MergedOptionStringFormatter), timeout=defaulted(integer_spec(), 300), wait_between_attempts=defaulted(float_spec(), 5), greps=optional_spec(dictof(formatted_string, formatted_string)), command=optional_spec(listof(formatted_string)), port_open=optional_spec(listof(integer_spec())), file_value=optional_spec(dictof(formatted_string, formatted_string)), curl_result=optional_spec( dictof(formatted_string, formatted_string)), file_exists=optional_spec(listof(formatted_string)))
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_or_int_as_string_spec(), MergedOptionStringFormatter, expected_type=six.string_types) bucket_name = meta.key_names()['_key_name_0'] original_permission = sb.listof(resource_policy_dict()).normalise( meta.at("permission"), NotSpecified if "permission" not in val else val["permission"]) deny_permission = sb.listof( resource_policy_dict(effect='Deny')).normalise( meta.at("deny_permission"), NotSpecified if "deny_permission" not in val else val["deny_permission"]) allow_permission = sb.listof( resource_policy_dict(effect='Allow')).normalise( meta.at("allow_permission"), NotSpecified if "allow_permission" not in val else val["allow_permission"]) val = val.wrapped() val['permission'] = original_permission + deny_permission + allow_permission return sb.create_spec( Bucket, name=sb.overridden(bucket_name), location=sb.required(formatted_string), permission=sb.container_spec( Document, sb.listof(resource_policy_statement_spec( 'bucket', bucket_name))), tags=sb.dictof(sb.string_spec(), formatted_string)).normalise(meta, val)