示例#1
0
    def test__load_task_wrong_input_task_args(self, mock_isfile,
                                              mock_safe_load):
        mock_safe_load.side_effect = yaml.ParserError("foo")
        mock_isfile.side_effect = (True, False)
        # use real file to avoid mocking open
        task_file = __file__

        e = self.assertRaises(task.FailedToLoadTask,
                              self.task._load_and_validate_task, self.real_api,
                              task_file, raw_args="{'test': {}")
        self.assertEqual("Invalid --task-args passed:\n\n\t Value has to be "
                         "YAML or JSON. Details:\n\nfoo", e.format_message())
        mock_safe_load.assert_called_once_with("{'test': {}")

        # the case #2
        mock_safe_load.reset_mock()
        mock_isfile.side_effect = (True, False)
        e = self.assertRaises(task.FailedToLoadTask,
                              self.task._load_and_validate_task, self.real_api,
                              task_file, raw_args="[]")
        self.assertEqual("Invalid --task-args passed:\n\n\t Value has to be "
                         "YAML or JSON. Details:\n\nfoo", e.format_message())
        mock_safe_load.assert_called_once_with("[]")

        # the case #3
        mock_safe_load.reset_mock()
        mock_isfile.side_effect = (True, False)
        e = self.assertRaises(task.FailedToLoadTask,
                              self.task._load_and_validate_task, self.real_api,
                              task_file, raw_args="foo")
        self.assertEqual("Invalid --task-args passed:\n\n\t Value has to be "
                         "YAML or JSON. Details:\n\nfoo", e.format_message())
        mock_safe_load.assert_called_once_with("foo")
示例#2
0
    def _load_and_validate_task(self,
                                api,
                                task_file,
                                args_file=None,
                                raw_args=None):
        """Load, render and validate tasks template from file with passed args.

        :param task_file: Path to file with input task
        :param raw_args: JSON or YAML representation of dict with args that
            will be used to render input task with jinja2
        :param args_file: Path to file with JSON or YAML representation
            of dict, that will be used to render input with jinja2. If both
            specified task_args and task_args_file they will be merged.
            raw_args has bigger priority so it will update values
            from args_file.
        :returns: Str with loaded and rendered task
        """

        print(cliutils.make_header("Preparing input task"))

        try:
            input_task = open(task_file).read()
        except IOError as err:
            raise FailedToLoadTask(source="--task",
                                   msg="Error reading %s: %s" %
                                   (task_file, err))

        task_dir = os.path.expanduser(os.path.dirname(task_file)) or "./"

        task_args = {}
        if args_file:
            try:
                task_args.update(yaml.safe_load(open(args_file).read()))
            except yaml.ParserError as e:
                raise FailedToLoadTask(
                    source="--task-args-file",
                    msg="File '%s' has to be YAML or JSON. Details:\n\n%s" %
                    (args_file, e))
            except IOError as err:
                raise FailedToLoadTask(source="--task-args-file",
                                       msg="Error reading %s: %s" %
                                       (args_file, err))

        if raw_args:
            try:
                data = yaml.safe_load(raw_args)
                if isinstance(data, (six.text_type, six.string_types)):
                    raise yaml.ParserError("String '%s' doesn't look like a "
                                           "dictionary." % raw_args)
                task_args.update(data)
            except yaml.ParserError as e:
                args = [
                    keypair.split("=", 1) for keypair in raw_args.split(",")
                ]
                if len([a for a in args if len(a) != 1]) != len(args):
                    raise FailedToLoadTask(
                        source="--task-args",
                        msg="Value has to be YAML or JSON. Details:\n\n%s" % e)
                else:
                    task_args.update(dict(args))

        try:
            rendered_task = api.task.render_template(task_template=input_task,
                                                     template_dir=task_dir,
                                                     **task_args)
        except Exception as e:
            raise FailedToLoadTask(
                source="--task",
                msg="Failed to render task template.\n\n%s" % e)

        print("Task is:\n%s\n" % rendered_task.strip())
        try:
            parsed_task = yaml.safe_load(rendered_task)
        except Exception as e:
            raise FailedToLoadTask(
                source="--task",
                msg="Wrong format of rendered input task. It should be YAML or"
                " JSON. Details:\n\n%s" % e)

        print("Task syntax is correct :)")
        return parsed_task