示例#1
0
 def test_render_jinja_payload_logs_jinja_vars_on_debug(self):
     """When debug is True, log jinja varables available."""
     payload = (
         "## template: jinja\n#!/bin/sh\necho hi from {{ v1.hostname }}")
     instance_data = {"v1": {"hostname": "foo"}, "instance-id": "iid"}
     expected_log = dedent("""\
         DEBUG: Converted jinja variables
         {
          "hostname": "foo",
          "instance-id": "iid",
          "instance_id": "iid",
          "v1": {
           "hostname": "foo"
          }
         }
         """)
     self.assertEqual(
         render_jinja_payload(
             payload=payload,
             payload_fn="myfile",
             instance_data=instance_data,
             debug=True,
         ),
         "#!/bin/sh\necho hi from foo",
     )
     self.assertEqual(expected_log, self.logs.getvalue())
示例#2
0
def handle_args(name, args):
    """Handle calls to 'cloud-init query' as a subcommand."""
    addLogHandlerCLI(LOG, log.DEBUG if args.debug else log.WARNING)
    if not any([args.list_keys, args.varname, args.format, args.dump_all]):
        LOG.error(
            "Expected one of the options: --all, --format,"
            " --list-keys or varname"
        )
        get_parser().print_help()
        return 1
    try:
        instance_data = _read_instance_data(
            args.instance_data, args.user_data, args.vendor_data
        )
    except (IOError, OSError):
        return 1
    if args.format:
        payload = "## template: jinja\n{fmt}".format(fmt=args.format)
        rendered_payload = render_jinja_payload(
            payload=payload,
            payload_fn="query commandline",
            instance_data=instance_data,
            debug=True if args.debug else False,
        )
        if rendered_payload:
            print(rendered_payload)
            return 0
        return 1

    # If not rendering a structured format above, query output will be either:
    #  - JSON dump of all instance-data/jinja variables
    #  - JSON dump of a value at an dict path into the instance-data dict.
    #  - a list of keys for a specific dict path into the instance-data dict.
    response = convert_jinja_instance_data(instance_data)
    if args.varname:
        jinja_vars_with_aliases = convert_jinja_instance_data(
            instance_data, include_key_aliases=True
        )
        try:
            response = _find_instance_data_leaf_by_varname_path(
                jinja_vars_without_aliases=response,
                jinja_vars_with_aliases=jinja_vars_with_aliases,
                varname=args.varname,
                list_keys=args.list_keys,
            )
        except (KeyError, ValueError) as e:
            LOG.error(e)
            return 1
    if args.list_keys:
        if not isinstance(response, dict):
            LOG.error(
                "--list-keys provided but '%s' is not a dict", args.varname
            )
            return 1
        response = "\n".join(sorted(response.keys()))
    if not isinstance(response, str):
        response = util.json_dumps(response)
    print(response)
    return 0
 def test_render_jinja_payload_replaces_missing_variables_and_warns(self):
     """Warn on missing jinja variables and replace the absent variable."""
     payload = ('## template: jinja\n#!/bin/sh\necho hi from {{ NOTHERE }}')
     instance_data = {'v1': {'hostname': 'foo'}, 'instance-id': 'iid'}
     self.assertEqual(
         render_jinja_payload(payload=payload,
                              payload_fn='myfile',
                              instance_data=instance_data),
         '#!/bin/sh\necho hi from CI_MISSING_JINJA_VAR/NOTHERE')
     expected_log = (
         'WARNING: Could not render jinja template variables in file'
         " 'myfile': 'NOTHERE'")
     self.assertIn(expected_log, self.logs.getvalue())
 def test_render_jinja_payload_replaces_missing_variables_and_warns(self):
     """Warn on missing jinja variables and replace the absent variable."""
     payload = (
         '## template: jinja\n#!/bin/sh\necho hi from {{ NOTHERE }}')
     instance_data = {'v1': {'hostname': 'foo'}, 'instance-id': 'iid'}
     self.assertEqual(
         render_jinja_payload(
             payload=payload, payload_fn='myfile',
             instance_data=instance_data),
         '#!/bin/sh\necho hi from CI_MISSING_JINJA_VAR/NOTHERE')
     expected_log = (
         'WARNING: Could not render jinja template variables in file'
         " 'myfile': 'NOTHERE'")
     self.assertIn(expected_log, self.logs.getvalue())
示例#5
0
 def test_render_jinja_payload_replaces_missing_variables_and_warns(self):
     """Warn on missing jinja variables and replace the absent variable."""
     payload = "## template: jinja\n#!/bin/sh\necho hi from {{ NOTHERE }}"
     instance_data = {"v1": {"hostname": "foo"}, "instance-id": "iid"}
     self.assertEqual(
         render_jinja_payload(
             payload=payload,
             payload_fn="myfile",
             instance_data=instance_data,
         ),
         "#!/bin/sh\necho hi from CI_MISSING_JINJA_VAR/NOTHERE",
     )
     expected_log = (
         "WARNING: Could not render jinja template variables in file"
         " 'myfile': 'NOTHERE'")
     self.assertIn(expected_log, self.logs.getvalue())
 def test_render_jinja_payload_logs_jinja_vars_on_debug(self):
     """When debug is True, log jinja varables available."""
     payload = (
         '## template: jinja\n#!/bin/sh\necho hi from {{ v1.hostname }}')
     instance_data = {'v1': {'hostname': 'foo'}, 'instance-id': 'iid'}
     expected_log = dedent("""\
         DEBUG: Converted jinja variables
         {
          "hostname": "foo",
          "instance_id": "iid",
          "v1": {
           "hostname": "foo"
          }
         }
         """)
     self.assertEqual(
         render_jinja_payload(
             payload=payload, payload_fn='myfile',
             instance_data=instance_data, debug=True),
         '#!/bin/sh\necho hi from foo')
     self.assertEqual(expected_log, self.logs.getvalue())
示例#7
0
def handle_args(name, args):
    """Handle calls to 'cloud-init query' as a subcommand."""
    paths = None
    addLogHandlerCLI(LOG, log.DEBUG if args.debug else log.WARNING)
    if not any([args.list_keys, args.varname, args.format, args.dump_all]):
        LOG.error('Expected one of the options: --all, --format,'
                  ' --list-keys or varname')
        get_parser().print_help()
        return 1

    uid = os.getuid()
    if not all([args.instance_data, args.user_data, args.vendor_data]):
        paths = read_cfg_paths()
    if args.instance_data:
        instance_data_fn = args.instance_data
    else:
        redacted_data_fn = os.path.join(paths.run_dir, INSTANCE_JSON_FILE)
        if uid == 0:
            sensitive_data_fn = os.path.join(paths.run_dir,
                                             INSTANCE_JSON_SENSITIVE_FILE)
            if os.path.exists(sensitive_data_fn):
                instance_data_fn = sensitive_data_fn
            else:
                LOG.warning(
                    'Missing root-readable %s. Using redacted %s instead.',
                    sensitive_data_fn, redacted_data_fn)
                instance_data_fn = redacted_data_fn
        else:
            instance_data_fn = redacted_data_fn
    if args.user_data:
        user_data_fn = args.user_data
    else:
        user_data_fn = os.path.join(paths.instance_link, 'user-data.txt')
    if args.vendor_data:
        vendor_data_fn = args.vendor_data
    else:
        vendor_data_fn = os.path.join(paths.instance_link, 'vendor-data.txt')

    try:
        instance_json = util.load_file(instance_data_fn)
    except (IOError, OSError) as e:
        if e.errno == EACCES:
            LOG.error("No read permission on '%s'. Try sudo", instance_data_fn)
        else:
            LOG.error('Missing instance-data file: %s', instance_data_fn)
        return 1

    instance_data = util.load_json(instance_json)
    if uid != 0:
        instance_data['userdata'] = ('<%s> file:%s' %
                                     (REDACT_SENSITIVE_VALUE, user_data_fn))
        instance_data['vendordata'] = (
            '<%s> file:%s' % (REDACT_SENSITIVE_VALUE, vendor_data_fn))
    else:
        instance_data['userdata'] = load_userdata(user_data_fn)
        instance_data['vendordata'] = load_userdata(vendor_data_fn)
    if args.format:
        payload = '## template: jinja\n{fmt}'.format(fmt=args.format)
        rendered_payload = render_jinja_payload(
            payload=payload,
            payload_fn='query commandline',
            instance_data=instance_data,
            debug=True if args.debug else False)
        if rendered_payload:
            print(rendered_payload)
            return 0
        return 1

    response = convert_jinja_instance_data(instance_data)
    if args.varname:
        try:
            for var in args.varname.split('.'):
                response = response[var]
        except KeyError:
            LOG.error('Undefined instance-data key %s', args.varname)
            return 1
        if args.list_keys:
            if not isinstance(response, dict):
                LOG.error("--list-keys provided but '%s' is not a dict", var)
                return 1
            response = '\n'.join(sorted(response.keys()))
    elif args.list_keys:
        response = '\n'.join(sorted(response.keys()))
    if not isinstance(response, str):
        response = util.json_dumps(response)
    print(response)
    return 0
示例#8
0
def handle_args(name, args):
    """Handle calls to 'cloud-init query' as a subcommand."""
    paths = None
    addLogHandlerCLI(LOG, log.DEBUG if args.debug else log.WARNING)
    if not any([args.list_keys, args.varname, args.format, args.dump_all]):
        LOG.error(
            'Expected one of the options: --all, --format,'
            ' --list-keys or varname')
        get_parser().print_help()
        return 1

    uid = os.getuid()
    if not all([args.instance_data, args.user_data, args.vendor_data]):
        paths = read_cfg_paths()
    if not args.instance_data:
        if uid == 0:
            default_json_fn = INSTANCE_JSON_SENSITIVE_FILE
        else:
            default_json_fn = INSTANCE_JSON_FILE  # World readable
        instance_data_fn = os.path.join(paths.run_dir, default_json_fn)
    else:
        instance_data_fn = args.instance_data
    if not args.user_data:
        user_data_fn = os.path.join(paths.instance_link, 'user-data.txt')
    else:
        user_data_fn = args.user_data
    if not args.vendor_data:
        vendor_data_fn = os.path.join(paths.instance_link, 'vendor-data.txt')
    else:
        vendor_data_fn = args.vendor_data

    try:
        instance_json = util.load_file(instance_data_fn)
    except IOError:
        LOG.error('Missing instance-data.json file: %s', instance_data_fn)
        return 1

    instance_data = util.load_json(instance_json)
    if uid != 0:
        instance_data['userdata'] = (
            '<%s> file:%s' % (REDACT_SENSITIVE_VALUE, user_data_fn))
        instance_data['vendordata'] = (
            '<%s> file:%s' % (REDACT_SENSITIVE_VALUE, vendor_data_fn))
    else:
        instance_data['userdata'] = util.load_file(user_data_fn)
        instance_data['vendordata'] = util.load_file(vendor_data_fn)
    if args.format:
        payload = '## template: jinja\n{fmt}'.format(fmt=args.format)
        rendered_payload = render_jinja_payload(
            payload=payload, payload_fn='query commandline',
            instance_data=instance_data,
            debug=True if args.debug else False)
        if rendered_payload:
            print(rendered_payload)
            return 0
        return 1

    response = convert_jinja_instance_data(instance_data)
    if args.varname:
        try:
            for var in args.varname.split('.'):
                response = response[var]
        except KeyError:
            LOG.error('Undefined instance-data key %s', args.varname)
            return 1
        if args.list_keys:
            if not isinstance(response, dict):
                LOG.error("--list-keys provided but '%s' is not a dict", var)
                return 1
            response = '\n'.join(sorted(response.keys()))
    elif args.list_keys:
        response = '\n'.join(sorted(response.keys()))
    if not isinstance(response, six.string_types):
        response = util.json_dumps(response)
    print(response)
    return 0