Beispiel #1
0
 def test_allow_most_keys_to_be_duplicates_for_overrides(self):
     yaml_config = """
     namespace: prod
     stacks:
       - name: vpc
         class_path: blueprints.VPC
         variables:
           CIDR: 192.168.1.0/24
           CIDR: 192.168.2.0/24
     """
     doc = parse(yaml_config)
     self.assertEqual(
         doc["stacks"][0]["variables"]["CIDR"], "192.168.2.0/24"
     )
     yaml_config = """
     default_variables: &default_variables
       CIDR: 192.168.1.0/24
     namespace: prod
     stacks:
       - name: vpc
         class_path: blueprints.VPC
         variables:
           << : *default_variables
           CIDR: 192.168.2.0/24
     """
     doc = parse(yaml_config)
     self.assertEqual(
         doc["stacks"][0]["variables"]["CIDR"], "192.168.2.0/24"
     )
Beispiel #2
0
 def test_allow_most_keys_to_be_duplicates_for_overrides(self):
     yaml_config = """
     namespace: prod
     stacks:
       - name: vpc
         class_path: blueprints.VPC
         variables:
           CIDR: 192.168.1.0/24
           CIDR: 192.168.2.0/24
     """
     doc = parse(yaml_config)
     self.assertEqual(
         doc["stacks"][0]["variables"]["CIDR"], "192.168.2.0/24"
     )
     yaml_config = """
     default_variables: &default_variables
       CIDR: 192.168.1.0/24
     namespace: prod
     stacks:
       - name: vpc
         class_path: blueprints.VPC
         variables:
           << : *default_variables
           CIDR: 192.168.2.0/24
     """
     doc = parse(yaml_config)
     self.assertEqual(
         doc["stacks"][0]["variables"]["CIDR"], "192.168.2.0/24"
     )
Beispiel #3
0
 def test_raise_constructor_error_on_keyword_duplicate_key(self):
     """Some keys should never have a duplicate sibling. For example we
     treat `class_path` as a special "keyword" and disallow dupes."""
     yaml_config = """
     namespace: prod
     stacks:
       - name: vpc
         class_path: blueprints.VPC
         class_path: blueprints.Fake
     """
     with self.assertRaises(ConstructorError):
         parse(yaml_config)
Beispiel #4
0
 def test_raise_constructor_error_on_keyword_duplicate_key(self):
     """Some keys should never have a duplicate sibling. For example we
     treat `class_path` as a special "keyword" and disallow dupes."""
     yaml_config = """
     namespace: prod
     stacks:
       - name: vpc
         class_path: blueprints.VPC
         class_path: blueprints.Fake
     """
     with self.assertRaises(ConstructorError):
         parse(yaml_config)
Beispiel #5
0
    def test_parse_invalid_inner_keys(self):
        yaml_config = """
        namespace: prod
        stacks:
        - name: vpc
          class_path: blueprints.VPC
          garbage: yes
          variables:
            Foo: bar
        """

        with self.assertRaises(exceptions.InvalidConfig):
            parse(yaml_config)
Beispiel #6
0
    def test_parse_invalid_inner_keys(self):
        yaml_config = """
        namespace: prod
        stacks:
        - name: vpc
          class_path: blueprints.VPC
          garbage: yes
          variables:
            Foo: bar
        """

        with self.assertRaises(exceptions.InvalidConfig):
            parse(yaml_config)
Beispiel #7
0
 def test_raise_construct_error_on_duplicate_stack_name_dict(self):
     """Some mappings should never have a duplicate children. For example we
     treat `stacks` as a special mapping and disallow dupe children keys."""
     yaml_config = """
     namespace: prod
     stacks:
       my_vpc:
         class_path: blueprints.VPC1
       my_vpc:
         class_path: blueprints.VPC2
     """
     with self.assertRaises(ConstructorError):
         parse(yaml_config)
Beispiel #8
0
 def test_raise_construct_error_on_duplicate_stack_name_dict(self):
     """Some mappings should never have a duplicate children. For example we
     treat `stacks` as a special mapping and disallow dupe children keys."""
     yaml_config = """
     namespace: prod
     stacks:
       my_vpc:
         class_path: blueprints.VPC1
       my_vpc:
         class_path: blueprints.VPC2
     """
     with self.assertRaises(ConstructorError):
         parse(yaml_config)
Beispiel #9
0
 def test_parse_tags(self):
     config = parse("""
     namespace: prod
     tags:
       "a:b": "c"
       "hello": 1
       simple_tag: simple value
     """)
     self.assertEquals(config.tags, {
         "a:b": "c",
         "hello": "1",
         "simple_tag": "simple value"})
Beispiel #10
0
 def test_parse_tags(self):
     config = parse("""
     namespace: prod
     tags:
       "a:b": "c"
       "hello": 1
       simple_tag: simple value
     """)
     self.assertEquals(config.tags, {
         "a:b": "c",
         "hello": "1",
         "simple_tag": "simple value"})
Beispiel #11
0
    def test_parse_with_arbitrary_anchors(self):
        config = parse("""
        namespace: prod
        common_variables: &common_variables
          Foo: bar
        stacks:
        - name: vpc
          class_path: blueprints.VPC
          variables:
            << : *common_variables
        """)

        stack = config.stacks[0]
        self.assertEquals(stack.variables, {"Foo": "bar"})
Beispiel #12
0
    def test_parse_with_arbitrary_anchors(self):
        config = parse("""
        namespace: prod
        common_variables: &common_variables
          Foo: bar
        stacks:
        - name: vpc
          class_path: blueprints.VPC
          variables:
            << : *common_variables
        """)

        stack = config.stacks[0]
        self.assertEquals(stack.variables, {"Foo": "bar"})
Beispiel #13
0
    def test_parse_external_invalid(self):
        config = parse("""
        namespace: prod
        stacks:
        - name: vpc
          class_path: blueprints.VPC
          parameters:
            Foo: bar
        - name: external-vpc
          stack_name: some-other-vpc
          external: yes
        """)

        with self.assertRaises(exceptions.InvalidConfig):
            config.validate()
Beispiel #14
0
    def test_parse_with_deprecated_parameters(self):
        config = parse("""
        namespace: prod
        stacks:
        - name: vpc
          class_path: blueprints.VPC
          parameters:
            Foo: bar
        """)
        with self.assertRaises(exceptions.InvalidConfig) as ex:
            config.validate()

        error = ex.exception.errors['stacks'][0]['parameters'][0]
        self.assertEquals(
            error.__str__(),
            "Stack definition vpc contains deprecated 'parameters', rather "
            "than 'variables'. Please update your config.")
Beispiel #15
0
    def test_parse_with_deprecated_parameters(self):
        config = parse("""
        namespace: prod
        stacks:
        - name: vpc
          class_path: blueprints.VPC
          parameters:
            Foo: bar
        """)
        with self.assertRaises(exceptions.InvalidConfig) as ex:
            config.validate()

        error = ex.exception.errors['stacks'][0]['parameters'][0]
        self.assertEquals(
            error.__str__(),
            "DEPRECATION: Stack definition vpc contains deprecated "
            "'parameters', rather than 'variables'. You are required to update"
            " your config. See https://stacker.readthedocs.io/en/latest/c"
            "onfig.html#variables for additional information.")
Beispiel #16
0
    def test_parse_with_deprecated_parameters(self):
        config = parse("""
        namespace: prod
        stacks:
        - name: vpc
          class_path: blueprints.VPC
          parameters:
            Foo: bar
        """)
        with self.assertRaises(exceptions.InvalidConfig) as ex:
            config.validate()

        error = ex.exception.errors['stacks'][0]['parameters'][0]
        self.assertEquals(
            error.__str__(),
            "DEPRECATION: Stack definition vpc contains deprecated "
            "'parameters', rather than 'variables'. You are required to update"
            " your config. See https://stacker.readthedocs.io/en/latest/c"
            "onfig.html#variables for additional information.")
Beispiel #17
0
    def test_parse_external(self):
        config = parse("""
        namespace: prod
        stacks:
        - name: vpc
          stack_name: cool-vpc
          class_path: blueprints.VPC
          parameters:
            Foo: bar
        - name: external-vpc
          stack_name: other-cool-vpc
          external: yes
        """)

        local_stack, external_stack = config.stacks
        self.assertIsInstance(local_stack, Stack)
        self.assertEquals(local_stack.name, 'vpc')
        self.assertEquals(local_stack.stack_name, 'cool-vpc')
        self.assertIsInstance(external_stack, ExternalStack)
        self.assertEquals(external_stack.name, 'external-vpc')
        self.assertEquals(external_stack.stack_name, 'other-cool-vpc')
Beispiel #18
0
    def test_parse(self):
        config_with_lists = """
        namespace: prod
        stacker_bucket: stacker-prod
        pre_build:
          - path: stacker.hooks.route53.create_domain
            required: true
            enabled: true
            args:
              domain: mydomain.com
        post_build:
          - path: stacker.hooks.route53.create_domain
            required: true
            enabled: true
            args:
              domain: mydomain.com
        pre_destroy:
          - path: stacker.hooks.route53.create_domain
            required: true
            enabled: true
            args:
              domain: mydomain.com
        post_destroy:
          - path: stacker.hooks.route53.create_domain
            required: true
            enabled: true
            args:
              domain: mydomain.com
        package_sources:
          s3:
            - bucket: acmecorpbucket
              key: public/acmecorp-blueprints-v1.zip
            - bucket: examplecorpbucket
              key: public/examplecorp-blueprints-v2.tar.gz
              requester_pays: true
            - bucket: anotherexamplebucket
              key: example-blueprints-v3.tar.gz
              use_latest: false
          git:
            - uri: [email protected]:acmecorp/stacker_blueprints.git
            - uri: [email protected]:remind101/stacker_blueprints.git
              tag: 1.0.0
              paths:
                - stacker_blueprints
            - uri: [email protected]:contoso/webapp.git
              branch: staging
            - uri: [email protected]:contoso/foo.git
              commit: 12345678
        tags:
          environment: production
        stacks:
        - name: vpc
          class_path: blueprints.VPC
          variables:
            PrivateSubnets:
            - 10.0.0.0/24
        - name: bastion
          class_path: blueprints.Bastion
          requires: ['vpc']
          variables:
            VpcId: ${output vpc::VpcId}
        """
        config_with_dicts = """
        namespace: prod
        stacker_bucket: stacker-prod
        pre_build:
          prebuild_createdomain:
            path: stacker.hooks.route53.create_domain
            required: true
            enabled: true
            args:
              domain: mydomain.com
        post_build:
          postbuild_createdomain:
            path: stacker.hooks.route53.create_domain
            required: true
            enabled: true
            args:
              domain: mydomain.com
        pre_destroy:
          predestroy_createdomain:
            path: stacker.hooks.route53.create_domain
            required: true
            enabled: true
            args:
              domain: mydomain.com
        post_destroy:
          postdestroy_createdomain:
            path: stacker.hooks.route53.create_domain
            required: true
            enabled: true
            args:
              domain: mydomain.com
        package_sources:
          s3:
            - bucket: acmecorpbucket
              key: public/acmecorp-blueprints-v1.zip
            - bucket: examplecorpbucket
              key: public/examplecorp-blueprints-v2.tar.gz
              requester_pays: true
            - bucket: anotherexamplebucket
              key: example-blueprints-v3.tar.gz
              use_latest: false
          git:
            - uri: [email protected]:acmecorp/stacker_blueprints.git
            - uri: [email protected]:remind101/stacker_blueprints.git
              tag: 1.0.0
              paths:
                - stacker_blueprints
            - uri: [email protected]:contoso/webapp.git
              branch: staging
            - uri: [email protected]:contoso/foo.git
              commit: 12345678
        tags:
          environment: production
        stacks:
          vpc:
            class_path: blueprints.VPC
            variables:
              PrivateSubnets:
              - 10.0.0.0/24
          bastion:
            class_path: blueprints.Bastion
            requires: ['vpc']
            variables:
              VpcId: ${output vpc::VpcId}
        """

        for raw_config in [config_with_lists, config_with_dicts]:
            config = parse(raw_config)

            config.validate()

            self.assertEqual(config.namespace, "prod")
            self.assertEqual(config.stacker_bucket, "stacker-prod")

            for hooks in [config.pre_build, config.post_build,
                          config.pre_destroy, config.post_destroy]:
                self.assertEqual(
                    hooks[0].path, "stacker.hooks.route53.create_domain")
                self.assertEqual(
                    hooks[0].required, True)
                self.assertEqual(
                    hooks[0].args, {"domain": "mydomain.com"})

            self.assertEqual(
                config.package_sources.s3[0].bucket,
                "acmecorpbucket")
            self.assertEqual(
                config.package_sources.s3[0].key,
                "public/acmecorp-blueprints-v1.zip")
            self.assertEqual(
                config.package_sources.s3[1].bucket,
                "examplecorpbucket")
            self.assertEqual(
                config.package_sources.s3[1].key,
                "public/examplecorp-blueprints-v2.tar.gz")
            self.assertEqual(
                config.package_sources.s3[1].requester_pays,
                True)
            self.assertEqual(
                config.package_sources.s3[2].use_latest,
                False)

            self.assertEqual(
                config.package_sources.git[0].uri,
                "[email protected]:acmecorp/stacker_blueprints.git")
            self.assertEqual(
                config.package_sources.git[1].uri,
                "[email protected]:remind101/stacker_blueprints.git")
            self.assertEqual(
                config.package_sources.git[1].tag,
                "1.0.0")
            self.assertEqual(
                config.package_sources.git[1].paths,
                ["stacker_blueprints"])
            self.assertEqual(
                config.package_sources.git[2].branch,
                "staging")

            self.assertEqual(config.tags, {"environment": "production"})

            self.assertEqual(len(config.stacks), 2)

            vpc_index = next(
                i for (i, d) in enumerate(config.stacks) if d.name == "vpc"
            )
            vpc = config.stacks[vpc_index]
            self.assertEqual(vpc.name, "vpc")
            self.assertEqual(vpc.class_path, "blueprints.VPC")
            self.assertEqual(vpc.requires, None)
            self.assertEqual(vpc.variables,
                             {"PrivateSubnets": ["10.0.0.0/24"]})

            bastion_index = next(
                i for (i, d) in enumerate(config.stacks) if d.name == "bastion"
            )
            bastion = config.stacks[bastion_index]
            self.assertEqual(bastion.name, "bastion")
            self.assertEqual(bastion.class_path, "blueprints.Bastion")
            self.assertEqual(bastion.requires, ["vpc"])
            self.assertEqual(bastion.variables,
                             {"VpcId": "${output vpc::VpcId}"})
Beispiel #19
0
    def test_parse(self):
        config = parse("""
        namespace: prod
        stacker_bucket: stacker-prod
        pre_build:
          - path: stacker.hooks.route53.create_domain
            required: true
            args:
              domain: mydomain.com
        post_build:
          - path: stacker.hooks.route53.create_domain
            required: true
            args:
              domain: mydomain.com
        pre_destroy:
          - path: stacker.hooks.route53.create_domain
            required: true
            args:
              domain: mydomain.com
        post_destroy:
          - path: stacker.hooks.route53.create_domain
            required: true
            args:
              domain: mydomain.com
        package_sources:
          git:
            - uri: [email protected]:acmecorp/stacker_blueprints.git
            - uri: [email protected]:remind101/stacker_blueprints.git
              tag: 1.0.0
              paths:
                - stacker_blueprints
            - uri: [email protected]:contoso/webapp.git
              branch: staging
            - uri: [email protected]:contoso/foo.git
              commit: 12345678
        tags:
          environment: production
        stacks:
        - name: vpc
          class_path: blueprints.VPC
          variables:
            PrivateSubnets:
            - 10.0.0.0/24
        - name: bastion
          class_path: blueprints.Bastion
          requires: ['vpc']
          variables:
            VpcId: ${output vpc::VpcId}
        """)

        config.validate()

        self.assertEqual(config.namespace, "prod")
        self.assertEqual(config.stacker_bucket, "stacker-prod")

        for hooks in [config.pre_build, config.post_build,
                      config.pre_destroy, config.post_destroy]:
            self.assertEqual(
                hooks[0].path, "stacker.hooks.route53.create_domain")
            self.assertEqual(
                hooks[0].required, True)
            self.assertEqual(
                hooks[0].args, {"domain": "mydomain.com"})

        self.assertEqual(
            config.package_sources.git[0].uri,
            "[email protected]:acmecorp/stacker_blueprints.git")
        self.assertEqual(
            config.package_sources.git[1].uri,
            "[email protected]:remind101/stacker_blueprints.git")
        self.assertEqual(
            config.package_sources.git[1].tag,
            "1.0.0")
        self.assertEqual(
            config.package_sources.git[1].paths,
            ["stacker_blueprints"])
        self.assertEqual(
            config.package_sources.git[2].branch,
            "staging")

        self.assertEqual(config.tags, {"environment": "production"})

        self.assertEqual(len(config.stacks), 2)
        vpc = config.stacks[0]
        self.assertEqual(vpc.name, "vpc")
        self.assertEqual(vpc.class_path, "blueprints.VPC")
        self.assertEqual(vpc.requires, None)
        self.assertEqual(vpc.variables, {"PrivateSubnets": ["10.0.0.0/24"]})

        bastion = config.stacks[1]
        self.assertEqual(bastion.name, "bastion")
        self.assertEqual(bastion.class_path, "blueprints.Bastion")
        self.assertEqual(bastion.requires, ["vpc"])
        self.assertEqual(bastion.variables, {"VpcId": "${output vpc::VpcId}"})
Beispiel #20
0
    def test_parse(self):
        config_with_lists = """
        namespace: prod
        stacker_bucket: stacker-prod
        pre_build:
          - path: stacker.hooks.route53.create_domain
            required: true
            enabled: true
            args:
              domain: mydomain.com
        post_build:
          - path: stacker.hooks.route53.create_domain
            required: true
            enabled: true
            args:
              domain: mydomain.com
        pre_destroy:
          - path: stacker.hooks.route53.create_domain
            required: true
            enabled: true
            args:
              domain: mydomain.com
        post_destroy:
          - path: stacker.hooks.route53.create_domain
            required: true
            enabled: true
            args:
              domain: mydomain.com
        package_sources:
          s3:
            - bucket: acmecorpbucket
              key: public/acmecorp-blueprints-v1.zip
            - bucket: examplecorpbucket
              key: public/examplecorp-blueprints-v2.tar.gz
              requester_pays: true
            - bucket: anotherexamplebucket
              key: example-blueprints-v3.tar.gz
              use_latest: false
              paths:
                - foo
              configs:
                - foo/config.yml
          git:
            - uri: [email protected]:acmecorp/stacker_blueprints.git
            - uri: [email protected]:remind101/stacker_blueprints.git
              tag: 1.0.0
              paths:
                - stacker_blueprints
            - uri: [email protected]:contoso/webapp.git
              branch: staging
            - uri: [email protected]:contoso/foo.git
              commit: 12345678
              paths:
                - bar
              configs:
                - bar/moreconfig.yml
        tags:
          environment: production
        stacks:
        - name: vpc
          class_path: blueprints.VPC
          variables:
            PrivateSubnets:
            - 10.0.0.0/24
        - name: bastion
          class_path: blueprints.Bastion
          requires: ['vpc']
          variables:
            VpcId: ${output vpc::VpcId}
        """
        config_with_dicts = """
        namespace: prod
        stacker_bucket: stacker-prod
        pre_build:
          prebuild_createdomain:
            path: stacker.hooks.route53.create_domain
            required: true
            enabled: true
            args:
              domain: mydomain.com
        post_build:
          postbuild_createdomain:
            path: stacker.hooks.route53.create_domain
            required: true
            enabled: true
            args:
              domain: mydomain.com
        pre_destroy:
          predestroy_createdomain:
            path: stacker.hooks.route53.create_domain
            required: true
            enabled: true
            args:
              domain: mydomain.com
        post_destroy:
          postdestroy_createdomain:
            path: stacker.hooks.route53.create_domain
            required: true
            enabled: true
            args:
              domain: mydomain.com
        package_sources:
          s3:
            - bucket: acmecorpbucket
              key: public/acmecorp-blueprints-v1.zip
            - bucket: examplecorpbucket
              key: public/examplecorp-blueprints-v2.tar.gz
              requester_pays: true
            - bucket: anotherexamplebucket
              key: example-blueprints-v3.tar.gz
              use_latest: false
              paths:
                - foo
              configs:
                - foo/config.yml
          git:
            - uri: [email protected]:acmecorp/stacker_blueprints.git
            - uri: [email protected]:remind101/stacker_blueprints.git
              tag: 1.0.0
              paths:
                - stacker_blueprints
            - uri: [email protected]:contoso/webapp.git
              branch: staging
            - uri: [email protected]:contoso/foo.git
              commit: 12345678
              paths:
                - bar
              configs:
                - bar/moreconfig.yml
        tags:
          environment: production
        stacks:
          vpc:
            class_path: blueprints.VPC
            variables:
              PrivateSubnets:
              - 10.0.0.0/24
          bastion:
            class_path: blueprints.Bastion
            requires: ['vpc']
            variables:
              VpcId: ${output vpc::VpcId}
        """

        for raw_config in [config_with_lists, config_with_dicts]:
            config = parse(raw_config)

            config.validate()

            self.assertEqual(config.namespace, "prod")
            self.assertEqual(config.stacker_bucket, "stacker-prod")

            for hooks in [config.pre_build, config.post_build,
                          config.pre_destroy, config.post_destroy]:
                self.assertEqual(
                    hooks[0].path, "stacker.hooks.route53.create_domain")
                self.assertEqual(
                    hooks[0].required, True)
                self.assertEqual(
                    hooks[0].args, {"domain": "mydomain.com"})

            self.assertEqual(
                config.package_sources.s3[0].bucket,
                "acmecorpbucket")
            self.assertEqual(
                config.package_sources.s3[0].key,
                "public/acmecorp-blueprints-v1.zip")
            self.assertEqual(
                config.package_sources.s3[1].bucket,
                "examplecorpbucket")
            self.assertEqual(
                config.package_sources.s3[1].key,
                "public/examplecorp-blueprints-v2.tar.gz")
            self.assertEqual(
                config.package_sources.s3[1].requester_pays,
                True)
            self.assertEqual(
                config.package_sources.s3[2].use_latest,
                False)

            self.assertEqual(
                config.package_sources.git[0].uri,
                "[email protected]:acmecorp/stacker_blueprints.git")
            self.assertEqual(
                config.package_sources.git[1].uri,
                "[email protected]:remind101/stacker_blueprints.git")
            self.assertEqual(
                config.package_sources.git[1].tag,
                "1.0.0")
            self.assertEqual(
                config.package_sources.git[1].paths,
                ["stacker_blueprints"])
            self.assertEqual(
                config.package_sources.git[2].branch,
                "staging")

            self.assertEqual(config.tags, {"environment": "production"})

            self.assertEqual(len(config.stacks), 2)

            vpc_index = next(
                i for (i, d) in enumerate(config.stacks) if d.name == "vpc"
            )
            vpc = config.stacks[vpc_index]
            self.assertEqual(vpc.name, "vpc")
            self.assertEqual(vpc.class_path, "blueprints.VPC")
            self.assertEqual(vpc.requires, None)
            self.assertEqual(vpc.variables,
                             {"PrivateSubnets": ["10.0.0.0/24"]})

            bastion_index = next(
                i for (i, d) in enumerate(config.stacks) if d.name == "bastion"
            )
            bastion = config.stacks[bastion_index]
            self.assertEqual(bastion.name, "bastion")
            self.assertEqual(bastion.class_path, "blueprints.Bastion")
            self.assertEqual(bastion.requires, ["vpc"])
            self.assertEqual(bastion.variables,
                             {"VpcId": "${output vpc::VpcId}"})