Example #1
0
 def tags_spec(self):
     # http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#tag-restrictions
     # Keys = 127 UTF-8 '^aws:' reserved. Values = 255 UTF-8
     return dictof(
           valid_string_spec(validators.regexed("^.{0,127}$"))
         , formatted(string_spec(), after_format=valid_string_spec(validators.regexed("^(?!aws:).{0,255}$")), formatter=MergedOptionStringFormatter)
         )
Example #2
0
 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()
         )
Example #3
0
 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
         )
Example #4
0
    def image_name_spec(self):
        """
        Image names are constrained by what docker wants

        And by the fact that option_merge means we can't have keys with dots in them.
        Otherwise if we have something like "ubuntu14.04" as an image, then when we do
        {images.ubuntu14.04.image_name} it'll look for config["images"]["ubuntu14"]["04"]["image_name"]
        instead of config["images"]["ubuntu14.04"]["image_name"] which is unlikely to be the
        desired result.
        """
        return valid_string_spec(
            validators.no_whitespace(),
            validators.regexed("^[a-zA-Z][a-zA-Z0-9-_\.]*$"))
Example #5
0
 def container_name_spec(self):
     """Just needs to be ascii"""
     return valid_string_spec(validators.no_whitespace(), validators.regexed("^[a-zA-Z][a-zA-Z0-9-_\.]*$"))
Example #6
0
            if isinstance(val, Command):
                result.append(val)
            else:
                result.extend(val)
        return result


class has_a_space(validators.Validator):
    def validate(self, meta, val):
        if ' ' not in val:
            raise BadOption(
                "Expected string to have a space (<ACTION> <COMMAND>)",
                meta=meta,
                got=val)
        return val


string_command_spec = lambda: sb.container_spec(
    Command, sb.valid_string_spec(has_a_space()))

# Only support ADD commands for the dictionary representation atm
dict_key = sb.valid_string_spec(validators.choice("ADD"))
dictionary_command_spec = lambda: convert_dict_command_spec(
    sb.dictof(dict_key, complex_ADD_spec()))

# The main spec
# We match against, strings, lists, dictionaries and Command objects with different specs
command_spec = lambda: sb.match_spec(
    (six.string_types, string_command_spec()), (list, array_command_spec()),
    (dict, dictionary_command_spec()), (Command, sb.any_spec()))
Example #7
0
            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(
                sb.valid_string_spec(
                    validators.regexed(r"^(LogicalResourceId/.*|\*)$")))),
        NotResource=sb.optional_spec(
            sb.listof(
                sb.valid_string_spec(
                    validators.regexed(r"^(LogicalResourceId/.*|\*)$")))),
        Condition=sb.optional_spec(sb.dictionary_spec()))))
Example #8
0
 def container_name_spec(self):
     """Just needs to be ascii"""
     return valid_string_spec(
         validators.no_whitespace(),
         validators.regexed("^[a-zA-Z][a-zA-Z0-9-_\.]*$"))
Example #9
0
 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))
Example #10
0
            spec = complex_ADD_spec()
        else:
            spec = complex_COPY_spec()

        result = []

        for val in spec.normalise(meta.at(items[0]), items[1]):
            if isinstance(val, Command):
                result.append(val)
            else:
                result.extend(val)

        return result

class has_a_space(validators.Validator):
    def validate(self, meta, val):
        if ' ' not in val:
            raise BadOption("Expected string to have a space (<ACTION> <COMMAND>)", meta=meta, got=val)
        return val

string_command_spec = lambda: sb.container_spec(Command, sb.valid_string_spec(has_a_space()))

# The main spec
# We match against, strings, lists, dictionaries and Command objects with different specs
command_spec = lambda: sb.match_spec(
      (six.string_types, string_command_spec())
    , (list, array_command_spec())
    , (dict, convert_dict_command_spec())
    , (Command, sb.any_spec())
    )
Example #11
0
    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)
            )
Example #12
0
    def normalise(self, meta, val):
        result = []
        for val in self.spec.normalise(meta, val).values():
            if isinstance(val, Command):
                result.append(val)
            else:
                result.extend(val)
        return result

class has_a_space(validators.Validator):
    def validate(self, meta, val):
        if ' ' not in val:
            raise BadOption("Expected string to have a space (<ACTION> <COMMAND>)", meta=meta, got=val)
        return val

string_command_spec = lambda: sb.container_spec(Command, sb.valid_string_spec(has_a_space()))

# Only support ADD commands for the dictionary representation atm
dict_key = sb.valid_string_spec(validators.choice("ADD"))
dictionary_command_spec = lambda: convert_dict_command_spec(sb.dictof(dict_key, complex_ADD_spec()))

# The main spec
# We match against, strings, lists, dictionaries and Command objects with different specs
command_spec = lambda: sb.match_spec(
      (six.string_types, string_command_spec())
    , (list, array_command_spec())
    , (dict, dictionary_command_spec())
    , (Command, sb.any_spec())
    )

Example #13
0
    def normalise(self, meta, val):
        result = []
        for val in self.spec.normalise(meta, val).values():
            if isinstance(val, Command):
                result.append(val)
            else:
                result.extend(val)
        return result

class has_a_space(validators.Validator):
    def validate(self, meta, val):
        if ' ' not in val:
            raise BadOption("Expected string to have a space (<ACTION> <COMMAND>)", meta=meta, got=val)
        return val

string_command_spec = lambda: sb.container_spec(Command, sb.valid_string_spec(has_a_space()))

# Only support ADD commands for the dictionary representation atm
dict_key = sb.valid_string_spec(validators.choice("ADD"))
dictionary_command_spec = lambda: convert_dict_command_spec(sb.dictof(dict_key, complex_ADD_spec()))

# The main spec
# We match against, strings, lists, dictionaries and Command objects with different specs
command_spec = lambda: sb.match_spec(
      (six.string_types, string_command_spec())
    , (list, array_command_spec())
    , (dict, dictionary_command_spec())
    , (Command, sb.any_spec())
    )