示例#1
0
 def test_has_related_image_envs(self, var, does_have):
     data = {
         'kind': 'ClusterServiceVersion',
         'spec': {
             'install': {
                 'spec': {
                     'deployments': [{
                         'spec': {
                             'template': {
                                 'spec': {
                                     'containers': [{
                                         'name': 'spam',
                                         'image': 'eggs',
                                         'env': []
                                     }]
                                 }
                             }
                         }
                     }]
                 }
             }
         }
     }
     if var is not None:
         deployment = data['spec']['install']['spec']['deployments'][0]
         deployment['spec']['template']['spec']['containers'][0][
             'env'].append(var)
     csv = OperatorCSV('original.yaml', data)
     assert csv.has_related_image_envs() == does_have
示例#2
0
    def test_dump(self, tmpdir):
        path = tmpdir.join("original.yaml")
        csv = OperatorCSV(str(path), ORIGINAL.data)
        csv.dump()

        content = path.read()
        # Formatting does not necessarily have to match, at least check the data...
        assert yaml.load(content) == csv.data
        # ...and that the comment was preserved
        assert content.startswith('# A meaningful comment')
示例#3
0
    def test_valuefrom_references_not_allowed(self):
        data = ORIGINAL.data
        env_path = EGGS.path[:-1]
        env = chain_get(data, env_path)
        env["valueFrom"] = "somewhere"

        csv = OperatorCSV("original.yaml", data)
        with pytest.raises(RuntimeError) as exc_info:
            csv.get_pullspecs()

        assert '"valueFrom" references are not supported' in str(
            exc_info.value)
示例#4
0
    def test_wrong_kind(self):
        data = ORIGINAL.data

        del data["kind"]
        with pytest.raises(NotOperatorCSV) as exc_info:
            OperatorCSV("original.yaml", data)
        assert str(exc_info.value) == "Not a ClusterServiceVersion"

        data["kind"] = "ClusterResourceDefinition"
        with pytest.raises(NotOperatorCSV) as exc_info:
            OperatorCSV("original.yaml", data)
        assert str(exc_info.value) == "Not a ClusterServiceVersion"
示例#5
0
    def test_from_file(self, tmpdir):
        path = tmpdir.join("original.yaml")
        path.write(ORIGINAL.content)

        csv = OperatorCSV.from_file(str(path))
        assert csv.path == str(path)
        assert csv.data == ORIGINAL.data
示例#6
0
    def test_replace_pullspecs_everywhere(self, caplog):
        csv = OperatorCSV("original.yaml", ORIGINAL.data)
        csv.replace_pullspecs_everywhere(self._replacement_pullspecs)
        assert csv.data == REPLACED_EVERYWHERE.data

        expected_logs = {
            "original.yaml - Replaced pullspec: {foo} -> {foo.replace}": 3,
            "original.yaml - Replaced pullspec: {bar} -> {bar.replace}": 3,
            "original.yaml - Replaced pullspec: {eggs} -> {eggs.replace}": 4,
            "original.yaml - Replaced pullspec: {spam} -> {spam.replace}": 3,
            "original.yaml - Replaced pullspec: {ham} -> {ham.replace}": 3,
            "original.yaml - Replaced pullspec: {jam} -> {jam.replace}": 3,
            "original.yaml - Replaced pullspec: {baz} -> {baz.replace}": 3,
            "original.yaml - Replaced pullspec: {p1} -> {p1.replace}": 3,
            "original.yaml - Replaced pullspec: {p2} -> {p2.replace}": 3,
        }
        for log, count in expected_logs.items():
            assert caplog.text.count(log.format(**PULLSPECS)) == count
示例#7
0
    def test_replace_pullspecs(self, caplog):
        csv = OperatorCSV("original.yaml", ORIGINAL.data)
        csv.replace_pullspecs(self._replacement_pullspecs)
        assert csv.data == REPLACED.data

        expected_logs = [
            "{file} - Replaced pullspec for relatedImage foo: {foo} -> {foo.replace}",
            "{file} - Replaced pullspec for relatedImage bar: {bar} -> {bar.replace}",
            "{file} - Replaced pullspec for RELATED_IMAGE_EGGS var: {eggs} -> {eggs.replace}",
            "{file} - Replaced pullspec for RELATED_IMAGE_P2 var: {p2} -> {p2.replace}",
            "{file} - Replaced pullspec for container spam: {spam} -> {spam.replace}",
            "{file} - Replaced pullspec for container ham: {ham} -> {ham.replace}",
            "{file} - Replaced pullspec for container jam: {jam} -> {jam.replace}",
            "{file} - Replaced pullspec for containerImage annotation: {baz} -> {baz.replace}",
            "{file} - Replaced pullspec for initContainer p1: {p1} -> {p1.replace}",
        ]
        for log in expected_logs:
            assert log.format(file="original.yaml", **PULLSPECS) in caplog.text
示例#8
0
    def test_get_pullspecs(self, caplog):
        csv = OperatorCSV("original.yaml", ORIGINAL.data)
        pullspecs = csv.get_pullspecs()
        assert pullspecs == self._original_pullspecs

        expected_logs = [
            "original.yaml - Found pullspec for relatedImage foo: {foo}",
            "original.yaml - Found pullspec for relatedImage bar: {bar}",
            "original.yaml - Found pullspec for RELATED_IMAGE_EGGS var: {eggs}",
            "original.yaml - Found pullspec for RELATED_IMAGE_P2 var: {p2}",
            "original.yaml - Found pullspec for container spam: {spam}",
            "original.yaml - Found pullspec for container ham: {ham}",
            "original.yaml - Found pullspec for container jam: {jam}",
            "original.yaml - Found pullspec for containerImage annotation: {baz}",
            "original.yaml - Found pullspec for initContainer p1: {p1}",
        ]
        for log in expected_logs:
            assert log.format(**PULLSPECS) in caplog.text
示例#9
0
    def test_replace_only_some_pullspecs(self, caplog):
        replacement_pullspecs = self._replacement_pullspecs.copy()

        # Foo won't be replaced because replacement is identical
        replacement_pullspecs[FOO.value] = FOO.value
        # Bar won't be replaced because no replacement available
        del replacement_pullspecs[BAR.value]

        csv = OperatorCSV("original.yaml", ORIGINAL.data)
        csv.replace_pullspecs(replacement_pullspecs)

        assert FOO.find_in_data(csv.data) == FOO.value
        assert BAR.find_in_data(csv.data) == BAR.value

        foo_log = "original.yaml - Replaced pullspec for related image foo: {foo}"
        bar_log = "original.yaml - Replaced pullspec for related image bar: {bar}"

        assert foo_log.format(foo=FOO) not in caplog.text
        assert bar_log.format(bar=BAR) not in caplog.text
示例#10
0
    def test_set_related_images(self, caplog):
        data = ORIGINAL.data
        csv = OperatorCSV("original.yaml", data)
        csv.set_related_images()

        # the order is:
        #   1. existing relatedImages
        #   2. annotations
        #   3. containers
        #   4. initContainers
        #   5. container env vars
        #   6. initContainer env vars
        expected_related_images = [
            CommentedMap([("name", name), ("image", pullspec.value.to_str())])
            for name, pullspec in [
                ("foo", FOO),
                ("bar", BAR),
                ("baz-annotation", BAZ),
                ("spam", SPAM),
                ("ham", HAM),
                ("jam", JAM),
                ("p1", P1),
                ("eggs", EGGS),
                ("p2", P2),
            ]
        ]
        assert csv.data["spec"]["relatedImages"] == expected_related_images

        expected_logs = [
            "{path} - Set relatedImage foo (from relatedImage foo): {foo}",
            "{path} - Set relatedImage bar (from relatedImage bar): {bar}",
            "{path} - Set relatedImage baz-annotation (from containerImage annotation): {baz}",
            "{path} - Set relatedImage spam (from container spam): {spam}",
            "{path} - Set relatedImage ham (from container ham): {ham}",
            "{path} - Set relatedImage jam (from container jam): {jam}",
            "{path} - Set relatedImage p1 (from initContainer p1): {p1}",
            "{path} - Set relatedImage eggs (from RELATED_IMAGE_EGGS var): {eggs}",
            "{path} - Set relatedImage p2 (from RELATED_IMAGE_P2 var): {p2}",
        ]
        for log in expected_logs:
            assert log.format(path="original.yaml", **PULLSPECS) in caplog.text
示例#11
0
    def test_set_related_images_conflicts(self, related_images, containers,
                                          err_msg):
        data = {
            "kind": "ClusterServiceVersion",
            "spec": {
                "relatedImages": related_images,
                "install": {
                    "spec": {
                        "deployments": [{
                            "spec": {
                                "template": {
                                    "spec": {
                                        "containers": containers
                                    }
                                }
                            }
                        }]
                    }
                }
            }
        }
        csv = OperatorCSV("original.yaml", data)

        if err_msg is not None:
            with pytest.raises(RuntimeError) as exc_info:
                csv.set_related_images()
            assert str(exc_info.value) == err_msg.format(path="original.yaml")
        else:
            csv.set_related_images()
            updated_counts = Counter(
                x['name'] for x in csv.data['spec']['relatedImages'])
            # check that there are no duplicates in .spec.relatedImages
            for name, count in updated_counts.items():
                assert count == 1, 'Duplicate in relatedImages: {}'.format(
                    name)
示例#12
0
    def test_get_pullspecs_some_locations(self, rel_images, rel_envs,
                                          containers, annotations,
                                          init_rel_envs, init_containers):
        data = ORIGINAL.data
        expected = {p.value for p in PULLSPECS.values()}

        if not rel_images:
            expected -= {FOO.value, BAR.value}
            del data["spec"]["relatedImages"]
        deployments = chain_get(data,
                                ["spec", "install", "spec", "deployments"])
        if not rel_envs:
            expected -= {EGGS.value}
            for d in deployments:
                for c in chain_get(d,
                                   ["spec", "template", "spec", "containers"]):
                    c.pop("env", None)
        if not containers:
            expected -= {SPAM.value, HAM.value, JAM.value}
            for d in deployments:
                del d["spec"]["template"]["spec"]["containers"]
        if not annotations:
            expected -= {BAZ.value}
            del data["metadata"]["annotations"]
        if not init_rel_envs:
            expected -= {P2.value}
            for d in deployments:
                for c in chain_get(
                        d, ["spec", "template", "spec", "initContainers"],
                        default=[]):
                    c.pop("env", None)
        if not init_containers:
            expected -= {P1.value}
            for d in deployments:
                d["spec"]["template"]["spec"].pop("initContainers", None)

        csv = OperatorCSV("x.yaml", data)
        assert csv.get_pullspecs() == expected
示例#13
0
 def test_has_related_images(self, pullspecs, does_have):
     data = {'kind': 'ClusterServiceVersion', 'spec': {}}
     if pullspecs is not None:
         data['spec']['relatedImages'] = pullspecs
     csv = OperatorCSV('original.yaml', data)
     assert csv.has_related_images() == does_have