checks.py: support 'append' option
If 'append' is defined for a property, append the values from append options to the property. Note: The property must support to be a list of values. For example: with schema: schema = { "$schema": "http://json-schema.org/draft-04/schema#", "title": "Pungi Configuration", "type": "object", "definitions": { "list_of_strings": { "type": "array", "items": {"type": "string"}, }, "strings": { "anyOf": [ {"type": "string"}, {"$ref": "#/definitions/list_of_strings"}, ] }, }, "properties": { "release_name": {"type": "string"}, "repo": {"$ref": "#/definitions/strings", "append": "repo_from"} }, "additionalProperties": False, } and config: repo = "http://url/to/repo" repo_from = "Server" config will be updated to: repo = ["http://url/to/repo", "Server"] It supports multiple append options too, like: "repo": { "$ref": "#/definitions/strings", "append": ["repo_from", "source_repo_from"], } Signed-off-by: Qixiang Wan <qwan@redhat.com>
This commit is contained in:
parent
2aacefd9cd
commit
d1763fca7e
@ -40,6 +40,7 @@ import os.path
|
||||
import platform
|
||||
import jsonschema
|
||||
import re
|
||||
from kobo.shortcuts import force_list
|
||||
|
||||
from . import util
|
||||
|
||||
@ -263,12 +264,34 @@ def _extend_with_default_and_alias(validator_class):
|
||||
"In:\n%s" % (subschema['alias'], property, property, instance)
|
||||
errors.append(ConfigOptionWarning(msg))
|
||||
if property in instance:
|
||||
msg = "ERROR: Config option '%s' is an alias of '%s', only one can be used. In:\n%s" \
|
||||
% (subschema['alias'], property, instance)
|
||||
msg = "ERROR: Config option '%s' is an alias of '%s', only one can be used." \
|
||||
% (subschema['alias'], property)
|
||||
errors.append(ConfigOptionError(msg))
|
||||
instance.pop(subschema['alias'])
|
||||
else:
|
||||
instance.setdefault(property, instance.pop(subschema['alias']))
|
||||
# update instance for append option
|
||||
# If append is defined in schema, append values from append options to property. If property
|
||||
# is not present in instance, set it to empty list, and append the values from append options.
|
||||
# Note: property's schema must support a list of values.
|
||||
if "append" in subschema:
|
||||
appends = force_list(subschema['append'])
|
||||
for append in appends:
|
||||
if append in instance:
|
||||
msg = "WARNING: Config option '%s' is deprecated, its value will be appended to option '%s'. " \
|
||||
"In:\n%s" % (append, property, instance)
|
||||
errors.append(ConfigOptionWarning(msg))
|
||||
if property in instance:
|
||||
msg = "WARNING: Value from config option '%s' is now appended to option '%s'." \
|
||||
% (append, property)
|
||||
errors.append(ConfigOptionWarning(msg))
|
||||
instance[property] = force_list(instance[property])
|
||||
instance[property].extend(force_list(instance.pop(append)))
|
||||
else:
|
||||
msg = "WARNING: Config option '%s' is not found, but '%s' is specified, value from '%s' " \
|
||||
"is now added as '%s'." % (property, append, append, property)
|
||||
errors.append(ConfigOptionWarning(msg))
|
||||
instance[property] = instance.pop(append)
|
||||
yield errors
|
||||
|
||||
def _set_defaults(validator, properties, instance, schema):
|
||||
|
@ -357,6 +357,130 @@ class TestSchemaValidator(unittest.TestCase):
|
||||
self.assertEqual(config.get("release_name", None), "dummy product")
|
||||
self.assertEqual(config.get("foophase", {}).get("repo", None), "http://www.exampe.com/os")
|
||||
|
||||
@mock.patch('pungi.checks._make_schema')
|
||||
def test_append_option(self, make_schema):
|
||||
schema = {
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "Pungi Configuration",
|
||||
"type": "object",
|
||||
"definitions": {
|
||||
"list_of_strings": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
},
|
||||
"strings": {
|
||||
"anyOf": [
|
||||
{"type": "string"},
|
||||
{"$ref": "#/definitions/list_of_strings"},
|
||||
]
|
||||
},
|
||||
},
|
||||
"properties": {
|
||||
"release_name": {"type": "string"},
|
||||
"repo": {"$ref": "#/definitions/strings", "append": "repo_from"}
|
||||
},
|
||||
"additionalProperties": False,
|
||||
}
|
||||
make_schema.return_value = schema
|
||||
|
||||
string = """
|
||||
release_name = "dummy product"
|
||||
repo = "http://url/to/repo"
|
||||
repo_from = 'Server'
|
||||
"""
|
||||
config = self._load_conf_from_string(string)
|
||||
errors, warnings = checks.validate(config)
|
||||
self.assertEqual(len(errors), 0)
|
||||
self.assertEqual(len(warnings), 2)
|
||||
self.assertRegexpMatches(warnings[0], r"^WARNING: Config option 'repo_from' is deprecated, its value will be appended to option 'repo'.*")
|
||||
self.assertRegexpMatches(warnings[1], r"^WARNING: Value from config option 'repo_from' is now appended to option 'repo'")
|
||||
self.assertEqual(config.get("release_name", None), "dummy product")
|
||||
self.assertEqual(config.get("repo", None), ["http://url/to/repo", "Server"])
|
||||
|
||||
@mock.patch('pungi.checks._make_schema')
|
||||
def test_append_to_nonexist_option(self, make_schema):
|
||||
schema = {
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "Pungi Configuration",
|
||||
"type": "object",
|
||||
"definitions": {
|
||||
"list_of_strings": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
},
|
||||
"strings": {
|
||||
"anyOf": [
|
||||
{"type": "string"},
|
||||
{"$ref": "#/definitions/list_of_strings"},
|
||||
]
|
||||
},
|
||||
},
|
||||
"properties": {
|
||||
"release_name": {"type": "string"},
|
||||
"repo": {"$ref": "#/definitions/strings", "append": "repo_from"}
|
||||
},
|
||||
"additionalProperties": False,
|
||||
}
|
||||
make_schema.return_value = schema
|
||||
|
||||
string = """
|
||||
release_name = "dummy product"
|
||||
repo_from = ['http://url/to/repo', 'Server']
|
||||
"""
|
||||
config = self._load_conf_from_string(string)
|
||||
errors, warnings = checks.validate(config)
|
||||
self.assertEqual(len(errors), 0)
|
||||
self.assertEqual(len(warnings), 2)
|
||||
self.assertRegexpMatches(warnings[0], r"^WARNING: Config option 'repo_from' is deprecated, its value will be appended to option 'repo'.*")
|
||||
self.assertRegexpMatches(warnings[1], r"^WARNING: Config option 'repo' is not found, but 'repo_from' is specified,")
|
||||
self.assertEqual(config.get("release_name", None), "dummy product")
|
||||
self.assertEqual(config.get("repo", None), ["http://url/to/repo", "Server"])
|
||||
|
||||
@mock.patch('pungi.checks._make_schema')
|
||||
def test_multiple_appends(self, make_schema):
|
||||
schema = {
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "Pungi Configuration",
|
||||
"type": "object",
|
||||
"definitions": {
|
||||
"list_of_strings": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
},
|
||||
"strings": {
|
||||
"anyOf": [
|
||||
{"type": "string"},
|
||||
{"$ref": "#/definitions/list_of_strings"},
|
||||
]
|
||||
},
|
||||
},
|
||||
"properties": {
|
||||
"release_name": {"type": "string"},
|
||||
"repo": {
|
||||
"$ref": "#/definitions/strings",
|
||||
"append": ["repo_from", "source_repo_from"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": False,
|
||||
}
|
||||
make_schema.return_value = schema
|
||||
|
||||
string = """
|
||||
release_name = "dummy product"
|
||||
repo_from = ['http://url/to/repo', 'Server']
|
||||
source_repo_from = 'Client'
|
||||
"""
|
||||
config = self._load_conf_from_string(string)
|
||||
errors, warnings = checks.validate(config)
|
||||
self.assertEqual(len(errors), 0)
|
||||
self.assertEqual(len(warnings), 4)
|
||||
self.assertRegexpMatches(warnings[0], r"^WARNING: Config option 'repo_from' is deprecated, its value will be appended to option 'repo'.*")
|
||||
self.assertRegexpMatches(warnings[1], r"^WARNING: Config option 'repo' is not found, but 'repo_from' is specified,")
|
||||
self.assertRegexpMatches(warnings[2], r"^WARNING: Config option 'source_repo_from' is deprecated, its value will be appended to option 'repo'")
|
||||
self.assertRegexpMatches(warnings[3], r"^WARNING: Value from config option 'source_repo_from' is now appended to option 'repo'.")
|
||||
self.assertEqual(config.get("release_name", None), "dummy product")
|
||||
self.assertEqual(config.get("repo", None), ["http://url/to/repo", "Server", "Client"])
|
||||
|
||||
|
||||
class TestUmask(unittest.TestCase):
|
||||
def setUp(self):
|
||||
|
Loading…
Reference in New Issue
Block a user