Example #1
0
    def test_ok_single(self, manifest_dir):
        """Load manifest file with single object definition."""

        objs = manifest.load_file(
            os.path.join(manifest_dir, 'simple-deployment.yaml'))

        assert len(objs) == 1
        assert isinstance(objs[0], client.models.v1_deployment.V1Deployment)
Example #2
0
    def test_ok_multi(self, manifest_dir):
        """Load manifest file with multiple object definitions."""

        objs = manifest.load_file(
            os.path.join(manifest_dir, 'multi-obj-manifest.yaml'))

        assert len(objs) == 3
        assert isinstance(objs[0], client.models.v1_service.V1Service)
        assert isinstance(objs[1], client.models.v1_service.V1Service)
        assert isinstance(objs[2], client.models.v1_deployment.V1Deployment)
Example #3
0
def apply_manifest_from_marker(item, client):
    """Load manifests and create the API objects for the specified files.

    This gets called for every `pytest.mark.applymanifests` marker on
    test cases.

    Once a manifest has been loaded, the API objects will be registered
    with the test cases' TestMeta. This allows some easier control via
    the "kube" fixture, such as waiting for all objects to be created.

    Args:
        item: The pytest test item.
        client (manager.TestMeta): The metainfo object for the marked
            test case.
    """
    for mark in item.iter_markers(name='applymanifests'):
        dir_path = mark.args[0]
        files = mark.kwargs.get('files')

        # We expect the path specified to either be absolute or relative
        # from the test file. If the path is relative, add the directory
        # that the test file resides in as a prefix to the dir_path.
        if not os.path.isabs(dir_path):
            dir_path = os.path.abspath(
                os.path.join(os.path.dirname(item.fspath), dir_path))

        # If there are any files specified, we will only load those files.
        # Otherwise, we'll load everything in the directory.
        if files is None:
            objs = load_path(dir_path)
        else:
            objs = [
                obj for objs in load_file(os.path.join(dir_path, f))
                for f in files
            ]

        # For each of the loaded Kubernetes resources, we'll want to wrap it
        # in the equivalent kubetest wrapper. If the resource does not have
        # an equivalent kubetest wrapper, error out. We cannot reliably create
        # the resource without our ApiObject wrapper semantics.
        wrapped = []
        for obj in objs:
            found = False
            for klass in ApiObject.__subclasses__():
                if obj.kind == klass.__name__:
                    wrapped.append(klass(obj))
                    found = True
                    break
            if not found:
                raise ValueError(
                    'Unable to match loaded object to an internal wrapper '
                    'class: {}'.format(obj))

        client.register_objects(wrapped)
Example #4
0
def apply_manifest_from_marker(item: pytest.Item,
                               meta: manager.TestMeta) -> None:
    """Load a manifest and create the API objects for the specified file.

    This gets called for every `pytest.mark.applymanifest` marker on
    test cases.

    Once the manifest has been loaded, the API object(s) will be registered with
    the test cases' TestMeta. This allows easier control via the "kube" fixture,
    such as waiting for all objects to be created.

    Args:
        item: The pytest test item.
        meta: The metainfo object for the marked test case.
    """
    item_renderer = get_manifest_renderer_for_item(item)
    for mark in item.iter_markers(name="applymanifest"):
        path = mark.args[0]
        renderer = mark.kwargs.get("renderer", item_renderer)
        if not callable(renderer):
            raise TypeError("renderer given is not callable")

        # Normalize the path to be absolute.
        if not os.path.isabs(path):
            path = os.path.abspath(path)

        # Load the manifest
        context = dict(namespace=meta.ns,
                       test_node_id=meta.node_id,
                       test_name=meta.name)
        context_renderer = ContextRenderer(renderer, context)
        objs = load_file(path, renderer=context_renderer)

        # For each of the loaded Kubernetes resources, wrap it in the
        # equivalent kubetest wrapper. If the object does not yet have a
        # wrapper, error out. We cannot reliably create the resource
        # without our ApiObject wrapper semantics.
        wrapped = []
        found = False
        for obj in objs:
            for klass in ApiObject.__subclasses__():
                if obj.kind == klass.__name__:
                    wrapped.append(klass(obj))
                    found = True
                    break
            if not found:
                raise ValueError(
                    f"Unable to match loaded object to an internal wrapper class: {obj}",
                )

        meta.register_objects(wrapped)
Example #5
0
    def load(cls, path):
        """Load the Kubernetes resource from file.

        Generally, this is used to load the Kubernetes manifest files
        and parse them into their appropriate API Object type.

        Args:
            path (str): The path to the YAML config file (manifest)
                containing the configuration for the resource.

        Returns:
            ApiObject: The API object wrapper corresponding to the configuration
            loaded from manifest YAML file.
        """
        obj = load_file(path, cls.obj_type)
        return cls(obj)
Example #6
0
def apply_manifest_from_marker(item, client):
    """Load a manifest and create the API objects for teh specified file.

    This gets called for every `pytest.mark.applymanifest` marker on
    test cases.

    Once the manifest has been loaded, the API object(s) will be registered
    with the test cases' TestMeta. This allows easier control via the
    "kube" fixture, such as waiting for all objects to be created.

    Args:
        item: The pytest test item.
        client (manager.TestMeta): The metainfo object for the marked
            test case.
    """
    for mark in item.iter_markers(name='applymanifest'):
        path = mark.args[0]

        # Normalize the path to be absolute.
        if not os.path.isabs(path):
            path = os.path.abspath(path)

        # Load the manifest
        objs = load_file(path)

        # For each of the loaded Kubernetes resources, wrap it in the
        # equivalent kubetest wrapper. If the object does not yet have a
        # wrapper, error out. We cannot reliably create the resource
        # without our ApiObject wrapper semantics.
        wrapped = []
        found = False
        for obj in objs:
            for klass in ApiObject.__subclasses__():
                if obj.kind == klass.__name__:
                    wrapped.append(klass(obj))
                    found = True
                    break
            if not found:
                raise ValueError(
                    'Unable to match loaded object to an internal wrapper '
                    'class: {}'.format(obj))

        client.register_objects(wrapped)
Example #7
0
    def load(cls, path):
        """Load the Kubernetes resource from file.

        Generally, this is used to load the Kubernetes manifest files
        and parse them into their appropriate API Object type.

        Args:
            path (str): The path to the YAML config file (manifest)
                containing the configuration for the resource.

        Returns:
            ApiObject: The API object wrapper corresponding to the configuration
            loaded from manifest YAML file.
        """
        objs = load_file(path)
        if len(objs) != 1:
            raise ValueError(
                'Unable to load resource from file - multiple resources found '
                'in specified file.')
        return cls(objs[0])
Example #8
0
    def test_invalid_yaml(self, manifest_dir):
        """Load manifest file with invalid YAML."""

        with pytest.raises(yaml.YAMLError):
            manifest.load_file(os.path.join(manifest_dir, 'invalid.yaml'))
Example #9
0
    def test_no_file(self, manifest_dir):
        """Load manifest file which does not exist."""

        with pytest.raises(FileNotFoundError):
            manifest.load_file(
                os.path.join(manifest_dir, 'file-does-not-exist.yaml'))
Example #10
0
    def load(cls, path: str, name: Optional[str] = None) -> 'ApiObject':
        """Load the Kubernetes resource from file.

        Generally, this is used to load the Kubernetes manifest files
        and parse them into their appropriate API Object type.

        Args:
            path: The path to the YAML config file (manifest)
                containing the configuration for the resource.
            name: The name of the resource to load. If the manifest file
                contains a single object definition for the type being
                loaded, it is not necessary to specify the name. If the
                manifest has multiple definitions containing the same
                type, a name is required to differentiate between them.
                If no name is specified in such case, an error is raised.

        Returns:
            The API object wrapper corresponding to the configuration
            loaded from manifest YAML file.

        Raises:
            ValueError: Multiple objects of the desired type were found in
            the manifest file and no name was specified to differentiate between
            them.
        """
        objs = load_file(path)

        # There is only one object defined in the manifest, so load it.
        # If the defined object does not match the type of the class being used
        # to load the definition, this will fail.
        if len(objs) == 1:
            return cls(objs[0])

        # Otherwise, there are multiple definitions in the manifest. Some of
        # these definitions may not match with the type we are trying to load,
        # so filter the loaded objects to only those which we care about.
        filtered = []
        for o in objs:
            if isinstance(o, cls.obj_type):
                filtered.append(o)

        if len(filtered) == 0:
            raise ValueError(
                'Unable to load resource from file - no resource definitions found '
                f'with type {cls.obj_type}.')

        if len(filtered) == 1:
            return cls(filtered[0])

        # If we get here, there are multiple objects of the same type defined. We
        # need to check that a name is provided and return the object whose name
        # matches.
        if not name:
            raise ValueError(
                'Unable to load resource from file - multiple resource definitions '
                f'found for {cls.obj_type}, but no name specified to select which one.'
            )

        for o in filtered:
            api_obj = cls(o)
            if api_obj.name == name:
                return api_obj

        raise ValueError(
            'Unable to load resource from file - multiple resource definitions found '
            f'for {cls.obj_type}, but none match specified name: {name}')
Example #11
0
def apply_manifests_from_marker(item: pytest.Item,
                                meta: manager.TestMeta) -> None:
    """Load manifests and create the API objects for the specified files.

    This gets called for every `pytest.mark.applymanifests` marker on test cases.

    Once a manifest has been loaded, the API objects will be registered with the
    test cases' TestMeta. This allows some easier control via the "kube" fixture,
    such as waiting for all objects to be created.

    Args:
        item: The pytest test item.
        meta: The metainfo object for the marked test case.
    """
    item_renderer = get_manifest_renderer_for_item(item)
    for mark in item.iter_markers(name="applymanifests"):
        dir_path = mark.args[0]
        files = mark.kwargs.get("files")
        renderer = mark.kwargs.get("renderer", item_renderer)

        if not callable(renderer):
            raise TypeError("renderer given is not callable")

        # We expect the path specified to either be absolute or relative
        # from the test file. If the path is relative, add the directory
        # that the test file resides in as a prefix to the dir_path.
        if not os.path.isabs(dir_path):
            dir_path = os.path.abspath(
                os.path.join(os.path.dirname(item.fspath), dir_path))

        # Setup template rendering context
        context = dict(
            dir_path=dir_path,
            namespace=meta.ns,
            test_node_id=meta.node_id,
            test_name=meta.name,
        )
        context_renderer = ContextRenderer(renderer, context)

        # If there are any files specified, we will only load those files.
        # Otherwise, we'll load everything in the directory.
        if files is None:
            objs = load_path(dir_path, renderer=context_renderer)
        else:
            objs = []
            context_renderer.context["objs"] = objs
            for f in files:
                objs.extend(
                    load_file(os.path.join(dir_path, f),
                              renderer=context_renderer))

        # For each of the loaded Kubernetes resources, we'll want to wrap it
        # in the equivalent kubetest wrapper. If the resource does not have
        # an equivalent kubetest wrapper, error out. We cannot reliably create
        # the resource without our ApiObject wrapper semantics.
        wrapped = []
        for obj in objs:
            found = False
            for klass in ApiObject.__subclasses__():
                if obj.kind == klass.__name__:
                    wrapped.append(klass(obj))
                    found = True
                    break
            if not found:
                raise ValueError(
                    f"Unable to match loaded object to an internal wrapper class: {obj}",
                )

        meta.register_objects(wrapped)