def test_database_update_package(fake_db):
    test_package = fake_db.get_package('test-package-2')
    test_package.installed = True
    test_package.version = Version(1, 2, 3)
    fake_db.update_package(test_package)
    test_package = fake_db.get_package('test-package-2')
    assert test_package.installed
    assert test_package.version == Version(1, 2, 3)
예제 #2
0
def test_manager_package_reset(package_manager, sonic_fs):
    package_manager.install('test-package-6=1.5.0')
    package_manager.install('test-package-6=2.0.0')

    package_manager.reset('test-package-6')
    upgraded_package = package_manager.get_installed_package('test-package-6')
    assert upgraded_package.entry.version == Version(1, 5, 0)
def test_database_get_package(fake_db):
    swss_package = fake_db.get_package('swss')
    assert swss_package.installed
    assert swss_package.built_in
    assert swss_package.repository == 'docker-orchagent'
    assert swss_package.default_reference == '1.0.0'
    assert swss_package.version == Version(1, 0, 0)
예제 #4
0
def test_manager_upgrade(package_manager, sonic_fs):
    package_manager.install('test-package-6=1.5.0')
    package = package_manager.get_installed_package('test-package-6')

    package_manager.install('test-package-6=2.0.0')
    upgraded_package = package_manager.get_installed_package('test-package-6')
    assert upgraded_package.entry.version == Version(2, 0, 0)
    assert upgraded_package.entry.default_reference == package.entry.default_reference
예제 #5
0
class ManifestSchema:
    """ ManifestSchema class describes and provides marshalling
    and unmarshalling methods.
    """
    class Marshaller:
        """ Base class for marshaling and un-marshaling. """
        def marshal(self, value):
            """ Validates and returns a valid manifest dictionary.

            Args:
                value: input value to validate.
            Returns: valid manifest node.
            """

            raise NotImplementedError

        def unmarshal(self, value):
            """ Un-marshals the manifest to a dictionary.

            Args:
                value: input value to validate.
            Returns: valid manifest node.
            """

            raise NotImplementedError

    @dataclass
    class ParsedMarshaller(Marshaller):
        """ Marshaller used on types which support class method "parse" """

        type: Any

        def marshal(self, value):
            try:
                return self.type.parse(value)
            except ValueError as err:
                raise ManifestError(f'Failed to marshal {value}: {err}')

        def unmarshal(self, value):
            try:
                if hasattr(value, 'deparse'):
                    return value.deparse()
                return str(value)
            except Exception as err:
                raise ManifestError(f'Failed to unmarshal {value}: {err}')

    @dataclass
    class DefaultMarshaller(Marshaller):
        """ Default marshaller that validates if the given
        value is instance of given type. """

        type: type

        def marshal(self, value):
            if not isinstance(value, self.type):
                raise ManifestError(
                    f'{value} is not of type {self.type.__name__}')
            return value

        def unmarshal(self, value):
            return value

    @dataclass
    class ManifestNode(Marshaller, ABC):
        """
        Base class for any manifest object.

        Attrs:
            key: String representing the key for this object.
        """

        key: str

    @dataclass
    class ManifestRoot(ManifestNode):
        items: List

        def marshal(self, value: Optional[dict]):
            result = {}
            value = value or {}

            if not isinstance(value, dict):
                raise ManifestError(
                    f'"{self.key}" field has to be a dictionary')

            for item in self.items:
                next_value = value.get(item.key)
                result[item.key] = item.marshal(next_value)
            return result

        def unmarshal(self, value):
            return_value = {}
            for item in self.items:
                return_value[item.key] = item.unmarshal(value[item.key])
            return return_value

    @dataclass
    class ManifestField(ManifestNode):
        type: Any
        default: Optional[Any] = None

        def marshal(self, value):
            if value is None:
                if self.default is not None:
                    return self.default
                raise ManifestError(
                    f'"{self.key}" is a required field but it is missing')
            try:
                return_value = self.type.marshal(value)
            except Exception as err:
                raise ManifestError(f'Failed to marshal {self.key}: {err}')
            return return_value

        def unmarshal(self, value):
            return self.type.unmarshal(value)

    @dataclass
    class ManifestArray(ManifestNode):
        type: Any

        def marshal(self, value):
            return_value = []
            value = value or []

            if not isinstance(value, list):
                raise ManifestError(f'"{self.key}" has to be of type list')

            try:
                for item in value:
                    return_value.append(self.type.marshal(item))
            except Exception as err:
                raise ManifestError(
                    f'Failed to convert {self.key}={value} to array: {err}')

            return return_value

        def unmarshal(self, value):
            return [self.type.unmarshal(item) for item in value]

    # TODO: add description for each field
    SCHEMA = ManifestRoot('root', [
        ManifestField('version', ParsedMarshaller(Version), Version(1, 0, 0)),
        ManifestRoot('package', [
            ManifestField('version', ParsedMarshaller(Version)),
            ManifestField('name', DefaultMarshaller(str)),
            ManifestField('description', DefaultMarshaller(str), ''),
            ManifestField('base-os', ParsedMarshaller(ComponentConstraints),
                          ComponentConstraints()),
            ManifestArray('depends', ParsedMarshaller(PackageConstraint)),
            ManifestArray('breaks', ParsedMarshaller(PackageConstraint)),
            ManifestField('init-cfg', DefaultMarshaller(dict), dict()),
            ManifestField('changelog', DefaultMarshaller(dict), dict()),
            ManifestField('debug-dump', DefaultMarshaller(str), ''),
        ]),
        ManifestRoot('service', [
            ManifestField('name', DefaultMarshaller(str)),
            ManifestArray('requires', DefaultMarshaller(str)),
            ManifestArray('requisite', DefaultMarshaller(str)),
            ManifestArray('wanted-by', DefaultMarshaller(str)),
            ManifestArray('after', DefaultMarshaller(str)),
            ManifestArray('before', DefaultMarshaller(str)),
            ManifestArray('dependent', DefaultMarshaller(str)),
            ManifestArray('dependent-of', DefaultMarshaller(str)),
            ManifestField('post-start-action', DefaultMarshaller(str), ''),
            ManifestField('pre-shutdown-action', DefaultMarshaller(str), ''),
            ManifestField('asic-service', DefaultMarshaller(bool), False),
            ManifestField('host-service', DefaultMarshaller(bool), True),
            ManifestField('delayed', DefaultMarshaller(bool), False),
            ManifestRoot('warm-shutdown', [
                ManifestArray('after', DefaultMarshaller(str)),
                ManifestArray('before', DefaultMarshaller(str)),
            ]),
            ManifestRoot('fast-shutdown', [
                ManifestArray('after', DefaultMarshaller(str)),
                ManifestArray('before', DefaultMarshaller(str)),
            ]),
        ]),
        ManifestRoot('container', [
            ManifestField('privileged', DefaultMarshaller(bool), False),
            ManifestArray('volumes', DefaultMarshaller(str)),
            ManifestArray(
                'mounts',
                ManifestRoot('mounts', [
                    ManifestField('source', DefaultMarshaller(str)),
                    ManifestField('target', DefaultMarshaller(str)),
                    ManifestField('type', DefaultMarshaller(str)),
                ])),
            ManifestField('environment', DefaultMarshaller(dict), dict()),
            ManifestArray('tmpfs', DefaultMarshaller(str)),
        ]),
        ManifestArray(
            'processes',
            ManifestRoot('processes', [
                ManifestField('name', DefaultMarshaller(str)),
                ManifestField('reconciles', DefaultMarshaller(bool), False),
            ])),
        ManifestRoot('cli', [
            ManifestField('mandatory', DefaultMarshaller(bool), False),
            ManifestField('show', DefaultMarshaller(str), ''),
            ManifestField('config', DefaultMarshaller(str), ''),
            ManifestField('clear', DefaultMarshaller(str), '')
        ])
    ])