diff --git a/cli/dcoscli/config/main.py b/cli/dcoscli/config/main.py index eb6d8db..4fb2767 100644 --- a/cli/dcoscli/config/main.py +++ b/cli/dcoscli/config/main.py @@ -132,7 +132,9 @@ def _set(name, value): return 1 toml_config[name] = python_value - return _save_config_file(config_path, toml_config) + _save_config_file(config_path, toml_config) + + return 0 def _append(name, value): @@ -149,7 +151,9 @@ def _append(name, value): return 1 toml_config[name] = toml_config.get(name, []) + python_value - return _save_config_file(config_path, toml_config) + _save_config_file(config_path, toml_config) + + return 0 def _prepend(name, value): @@ -166,7 +170,9 @@ def _prepend(name, value): return 1 toml_config[name] = python_value + toml_config.get(name, []) - return _save_config_file(config_path, toml_config) + _save_config_file(config_path, toml_config) + + return 0 def _unset(name, index): @@ -209,7 +215,9 @@ def _unset(name, index): 'Unsetting based on an index is only supported for lists')) return 1 - return _save_config_file(config_path, toml_config) + _save_config_file(config_path, toml_config) + + return 0 def _show(name): @@ -240,6 +248,38 @@ def _show(name): return 0 +def _validate(): + """ + :returns: process status + :rtype: int + """ + + _, toml_config = _load_config() + + root_schema = { + '$schema': 'http://json-schema.org/schema#', + 'type': 'object', + 'properties': {}, + 'additionalProperties': False, + } + + # Load the config schema from all the subsections into the root schema + for section in toml_config.keys(): + config_schema, err = _get_config_schema(section) + if err is not None: + emitter.publish(err) + return 1 + + root_schema['properties'][section] = config_schema + + err = util.validate_json(toml_config._dictionary, root_schema) + if err is not None: + emitter.publish(err) + return 1 + + return 0 + + def _generate_choice_msg(name, value): """ :param name: name of the property @@ -268,58 +308,18 @@ def _load_config(): return (config_path, config.mutable_load_from_path(config_path)) -def _validate(toml_config=_load_config()[1]): - """ - :param toml_config: TOML configuration object - :type toml_config: MutableToml or Toml - :returns: process status - :rtype: int - """ - - root_schema = { - '$schema': 'http://json-schema.org/schema#', - 'type': 'object', - 'properties': {}, - 'additionalProperties': False, - } - - # Load the config schema from all the subsections into the root schema - for section in toml_config.keys(): - config_schema, err = _get_config_schema(section) - if err is not None: - emitter.publish(err) - return 1 - - root_schema['properties'][section] = config_schema - - err = util.validate_json(toml_config._dictionary, root_schema) - if err is not None: - emitter.publish(err) - return 1 - - return 0 - - def _save_config_file(config_path, toml_config): """ :param config_path: path to configuration file. :type config_path: str :param toml_config: TOML configuration object :type toml_config: MutableToml or Toml - :returns: process status - :rtype: int """ serial = toml.dumps(toml_config._dictionary) - error_status = _validate(toml_config) - if error_status != 0: - return error_status - with open(config_path, 'w') as config_file: config_file.write(serial) - return 0 - def _get_config_schema(command): """ diff --git a/cli/dcoscli/data/config-schema/package.json b/cli/dcoscli/data/config-schema/package.json index 591e633..6e3db55 100644 --- a/cli/dcoscli/data/config-schema/package.json +++ b/cli/dcoscli/data/config-schema/package.json @@ -10,8 +10,7 @@ "title": "Package sources", "description": "The list of package source in search order", "default": [ "git://github.com/mesosphere/universe.git" ], - "additionalItems": false, - "uniqueItems": true + "additionalItems": false }, "cache": { "type": "string", diff --git a/cli/tests/integrations/cli/test_config.py b/cli/tests/integrations/cli/test_config.py index 3d75db8..5cad82d 100644 --- a/cli/tests/integrations/cli/test_config.py +++ b/cli/tests/integrations/cli/test_config.py @@ -118,7 +118,7 @@ def test_set_existing_integral_property(env): def test_append_empty_list(env): - _set_value('package.sources', '[]', env) + _unset_value('package.sources', None, env) _append_value( 'package.sources', 'git://github.com/mesosphere/universe.git', @@ -139,7 +139,7 @@ def test_append_empty_list(env): def test_prepend_empty_list(env): - _set_value('package.sources', '[]', env) + _unset_value('package.sources', None, env) _prepend_value( 'package.sources', 'https://github.com/mesosphere/universe/archive/master.zip', @@ -212,22 +212,19 @@ def test_prepend_non_list(env): def test_unset_property(env): - _unset_value('core.reporting', None, env) - _get_missing_value('core.reporting', env) - _set_value('core.reporting', 'false', env) + _unset_value('marathon.host', None, env) + _get_missing_value('marathon.host', env) + _set_value('marathon.host', 'localhost', env) -def test_property_validation(env): +def test_unset_missing_property(env): returncode, stdout, stderr = exec_command( - ['dcos', 'config', 'unset', 'marathon.host'], + ['dcos', 'config', 'unset', 'missing.property'], env) assert returncode == 1 assert stdout == b'' - assert stderr == b"""Error: 'host' is a required property -Path: marathon -Value: {"port": 8080} -""" + assert stderr == b"Property 'missing.property' doesn't exist\n" def test_unset_top_property(env): @@ -245,8 +242,9 @@ def test_unset_top_property(env): ) -def test_set_whole_list(env): - _set_value('package.sources', '[]', env) +def test_unset_whole_list(env): + _unset_value('package.sources', None, env) + _get_missing_value('package.sources', env) _set_value( 'package.sources', '["git://github.com/mesosphere/universe.git", ' @@ -309,6 +307,23 @@ def test_validate(env): assert stderr == b'' +def test_validation_error(env): + _unset_value('marathon.host', None, env) + + returncode, stdout, stderr = exec_command( + ['dcos', 'config', 'validate'], + env) + + assert returncode == 1 + assert stdout == b'' + assert stderr == b"""Error: 'host' is a required property +Path: marathon +Value: {"port": 8080} +""" + + _set_value('marathon.host', 'localhost', env) + + def test_set_property_key(env): returncode, stdout, stderr = exec_command( ['dcos', 'config', 'set', 'path.to.value', 'cool new value'], @@ -320,9 +335,9 @@ def test_set_property_key(env): def test_set_missing_property(env): - _unset_value('core.reporting', None, env) - _set_value('core.reporting', 'false', env) - _get_value('core.reporting', 'false', env) + _unset_value('marathon.host', None, env) + _set_value('marathon.host', 'localhost', env) + _get_value('marathon.host', 'localhost', env) def test_set_core_property(env): @@ -332,7 +347,6 @@ def test_set_core_property(env): def _set_value(key, value, env): - returncode, stdout, stderr = exec_command( ['dcos', 'config', 'set', key, value], env)