Beispiel #1
0
    def validate(self, remote, reconcile=True, env_map=None, **kwargs):
        """Attempts to validate package installation on the image.

        Even if reconcile=True, attempts to verify previous package
        installation offline before using networked tools to validate or
        install new packages.

        :param remote: A remote socket to the instance.
        :param reconcile: If false, all validators will only verify that a
            desired state is present, and fail if it is not. If true, all
            validators will attempt to enforce the desired state if possible,
            and succeed if this enforcement succeeds.
        :param env_map: A map of environment variables to pass to scripts.
        :raises ImageValidationError: If validation fails.
        """
        env_distro = env_map[self.DISTRO_KEY]
        env_family = self._DISTRO_FAMILES[env_distro]
        check, install = self._DISTRO_TOOLS[env_family]
        if not env_family:
            raise p_ex.ImageValidationError(
                _("Unknown distro: cannot verify or install packages."))
        try:
            check(self, remote)
        except (ex.SubprocessException, ex.RemoteCommandException):
            if reconcile:
                install(self, remote)
                check(self, remote)
            else:
                raise
Beispiel #2
0
    def validate(self,
                 remote,
                 test_only=False,
                 image_arguments=None,
                 **kwargs):
        """Attempts to validate package installation on the image.

        Even if test_only=False, attempts to verify previous package
        installation offline before using networked tools to validate or
        install new packages.

        :param remote: A remote socket to the instance.
        :param test_only: If true, all validators will only verify that a
            desired state is present, and fail if it is not. If false, all
            validators will attempt to enforce the desired state if possible,
            and succeed if this enforcement succeeds.
        :param image_arguments: A dictionary of image argument values keyed by
            argument name.
        :raises ImageValidationError: If validation fails.
        """
        env_distro = image_arguments[self.DISTRO_KEY]
        env_family = self._DISTRO_FAMILES[env_distro]
        check, install = self._DISTRO_TOOLS[env_family]
        if not env_family:
            raise p_ex.ImageValidationError(
                _("Unknown distro: cannot verify or install packages."))
        try:
            check(self, remote)
        except (ex.SubprocessException, ex.RemoteCommandException,
                RuntimeError):
            if not test_only:
                install(self, remote)
                check(self, remote)
            else:
                raise
Beispiel #3
0
    def validate(self,
                 remote,
                 test_only=False,
                 image_arguments=None,
                 **kwargs):
        """Attempts to validate depending on argument value.

        :param remote: A remote socket to the instance.
        :param test_only: If true, all validators will only verify that a
            desired state is present, and fail if it is not. If false, all
            validators will attempt to enforce the desired state if possible,
            and succeed if this enforcement succeeds.
        :param image_arguments: A dictionary of image argument values keyed by
            argument name.
        :raises ImageValidationError: If validation fails.
        """
        arg = self.argument_name
        if arg not in image_arguments:
            raise p_ex.ImageValidationError(
                _("Argument {name} not found.").format(name=arg))
        value = image_arguments[arg]
        if value in self.cases:
            self.cases[value].validate(remote,
                                       test_only=test_only,
                                       image_arguments=image_arguments)
Beispiel #4
0
    def test_any_validator(self):
        cls = images.SaharaAnyValidator

        class FakeValidator(images.SaharaImageValidatorBase):

            def __init__(self, mock_validate):
                self.mock_validate = mock_validate

            def validate(self, remote, test_only=False, **kwargs):
                self.mock_validate(remote, test_only=test_only, **kwargs)

        # One success short circuits validation
        always_tells_the_truth = FakeValidator(mock.Mock())
        validator = cls([always_tells_the_truth, always_tells_the_truth])
        validator.validate(None, test_only=False)
        self.assertEqual(always_tells_the_truth.mock_validate.call_count, 1)

        # All failures fails, and calls with test_only=True on all first
        always_lies = FakeValidator(
            mock.Mock(side_effect=p_ex.ImageValidationError("Oh no!")))
        validator = cls([always_lies, always_lies])
        try:
            validator.validate(None, test_only=False)
        except p_ex.ImageValidationError:
            pass
        self.assertEqual(always_lies.mock_validate.call_count, 4)

        # But it fails after a first pass if test_only=True.
        always_lies = FakeValidator(
            mock.Mock(side_effect=p_ex.ImageValidationError("Oh no!")))
        validator = cls([always_lies, always_lies])
        try:
            validator.validate(None, test_only=True)
        except p_ex.ImageValidationError:
            pass
        self.assertEqual(always_lies.mock_validate.call_count, 2)

        # One failure doesn't end iteration.
        always_tells_the_truth = FakeValidator(mock.Mock())
        always_lies = FakeValidator(
            mock.Mock(side_effect=p_ex.ImageValidationError("Oh no!")))
        validator = cls([always_lies, always_tells_the_truth])
        validator.validate(None, test_only=False)
        self.assertEqual(always_lies.mock_validate.call_count, 1)
        self.assertEqual(always_tells_the_truth.mock_validate.call_count, 1)
Beispiel #5
0
    def test_all_validator(self):
        cls = images.SaharaAllValidator

        # All pass
        always_tells_the_truth = mock.Mock()
        validator = cls([always_tells_the_truth, always_tells_the_truth])
        validator.validate(None, reconcile=True)
        self.assertEqual(always_tells_the_truth.validate.call_count, 2)
        always_tells_the_truth.validate.assert_called_with(None,
                                                           reconcile=True,
                                                           env_map=None)

        # Second fails
        always_tells_the_truth = mock.Mock()
        always_lies = mock.Mock(validate=mock.Mock(
            side_effect=p_ex.ImageValidationError("Boom!")))
        validator = cls([always_tells_the_truth, always_lies])
        try:
            validator.validate(None, reconcile=False)
        except p_ex.ImageValidationError:
            pass
        self.assertEqual(always_tells_the_truth.validate.call_count, 1)
        self.assertEqual(always_lies.validate.call_count, 1)
        always_tells_the_truth.validate.assert_called_with(None,
                                                           reconcile=False,
                                                           env_map=None)
        always_lies.validate.assert_called_with(None,
                                                reconcile=False,
                                                env_map=None)

        # First fails
        always_tells_the_truth = mock.Mock()
        always_lies = mock.Mock(validate=mock.Mock(
            side_effect=p_ex.ImageValidationError("Boom!")))
        validator = cls([always_lies, always_tells_the_truth])
        try:
            validator.validate(None, reconcile=False, env_map={})
        except p_ex.ImageValidationError:
            pass
        self.assertEqual(always_lies.validate.call_count, 1)
        always_lies.validate.assert_called_with(None,
                                                reconcile=False,
                                                env_map={})
        self.assertEqual(always_tells_the_truth.validate.call_count, 0)
Beispiel #6
0
    def validate(self,
                 remote,
                 test_only=False,
                 image_arguments=None,
                 **kwargs):
        """Attempts to validate the image.

        Before deferring to contained validators, performs one-time setup
        steps such as distro discovery.

        :param remote: A remote socket to the instance.
        :param test_only: If true, all validators will only verify that a
            desired state is present, and fail if it is not. If false, all
            validators will attempt to enforce the desired state if possible,
            and succeed if this enforcement succeeds.
        :param image_arguments: A dictionary of image argument values keyed by
            argument name.
        :raises ImageValidationError: If validation fails.
        """
        argument_values = {}
        for name, argument in six.iteritems(self.arguments):
            if name not in image_arguments:
                if argument.required:
                    raise p_ex.ImageValidationError(
                        _("Argument {name} is required for image "
                          "processing.").format(name=name))
                else:
                    argument_values[name] = argument.default
            else:
                value = image_arguments[name]
                choices = argument.choices
                if choices and value not in choices:
                    raise p_ex.ImageValidationError(
                        _("Value for argument {name} must be one of "
                          "{choices}.").format(name=name, choices=choices))
                else:
                    argument_values[name] = value
        argument_values[self.DISTRO_KEY] = remote.get_os_distrib()
        self.validator.validate(remote,
                                test_only=test_only,
                                image_arguments=argument_values)