diff --git a/cli/dcoscli/config/main.py b/cli/dcoscli/config/main.py index 1b226e4..11a8815 100644 --- a/cli/dcoscli/config/main.py +++ b/cli/dcoscli/config/main.py @@ -170,8 +170,6 @@ def _set(name, value): (name == 'core.email'): analytics.segment_identify(toml_config) - _save_config_file(config_path, toml_config) - _check_config(toml_config_pre, toml_config) _save_config_file(config_path, toml_config) diff --git a/cli/dcoscli/data/config-schema/core.json b/cli/dcoscli/data/config-schema/core.json index ee645f5..1cfe24a 100644 --- a/cli/dcoscli/data/config-schema/core.json +++ b/cli/dcoscli/data/config-schema/core.json @@ -9,6 +9,7 @@ }, "dcos_url": { "type": "string", + "pattern": "^(?:(?:https?)://)(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.?)+(?:[a-zA-Z]{2,6}\\.?|[a-zA-Z0-9-]{2,}\\.?)?|\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})(?::\\d+)?(?:/?|[/?]\\S+)$", "title": "DCOS URL", "description": "The URL to the location of the DCOS" }, @@ -30,6 +31,7 @@ }, "mesos_master_url": { "type": "string", + "pattern": "^(?:(?:https?)://)(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.?)+(?:[a-zA-Z]{2,6}\\.?|[a-zA-Z0-9-]{2,}\\.?)?|\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})(?::\\d+)?(?:/?|[/?]\\S+)$", "title": "Mesos Master URL", "description": "Mesos Master URL. Must be of the format: \"http://host:port\"" diff --git a/cli/dcoscli/data/config-schema/marathon.json b/cli/dcoscli/data/config-schema/marathon.json index 364e3cf..3c1be81 100644 --- a/cli/dcoscli/data/config-schema/marathon.json +++ b/cli/dcoscli/data/config-schema/marathon.json @@ -4,6 +4,7 @@ "properties": { "url": { "type": "string", + "pattern": "^(?:(?:https?)://)(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.?)+(?:[a-zA-Z]{2,6}\\.?|[a-zA-Z0-9-]{2,}\\.?)?|\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})(?::\\d+)?(?:/?|[/?]\\S+)$", "title": "Marathon base URL", "description": "Base URL for talking to Marathon. It overwrites the value specified in core.dcos_url", "default": "http://localhost:8080" diff --git a/cli/dcoscli/data/config-schema/package.json b/cli/dcoscli/data/config-schema/package.json index 591e633..ac78663 100644 --- a/cli/dcoscli/data/config-schema/package.json +++ b/cli/dcoscli/data/config-schema/package.json @@ -5,7 +5,8 @@ "sources": { "type": "array", "items": { - "type": "string" + "type": "string", + "pattern": "^((?:(?:(https?|file))://)(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.?)+(?:[a-zA-Z]{2,6}\\.?|[a-zA-Z0-9-]{2,}\\.?)?|\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})?(?::\\d+)?(?:/?|[/?]\\S+)|((git|ssh|https?)|(git@[\\w\\.]+))(:(//)?)([\\w\\.@\\:/\\-~]+)(\\.git)(/)?)$" }, "title": "Package sources", "description": "The list of package source in search order", diff --git a/cli/tests/integrations/test_config.py b/cli/tests/integrations/test_config.py index 3352b97..f9d4bd6 100644 --- a/cli/tests/integrations/test_config.py +++ b/cli/tests/integrations/test_config.py @@ -148,12 +148,12 @@ def test_prepend_empty_list(env): def test_append_list(env): _append_value( 'package.sources', - 'new_uri', + 'https://github.com/mesosphere/universe/archive/version-2.x.zip', env) _get_value( 'package.sources', ['https://github.com/mesosphere/universe/archive/version-1.x.zip', - 'new_uri'], + 'https://github.com/mesosphere/universe/archive/version-2.x.zip'], env) _unset_value('package.sources', '1', env) @@ -161,11 +161,11 @@ def test_append_list(env): def test_prepend_list(env): _prepend_value( 'package.sources', - 'new_uri', + 'https://github.com/mesosphere/universe/archive/version-2.x.zip', env) _get_value( 'package.sources', - ['new_uri', + ['https://github.com/mesosphere/universe/archive/version-2.x.zip', 'https://github.com/mesosphere/universe/archive/version-1.x.zip'], env) _unset_value('package.sources', '0', env) @@ -319,6 +319,111 @@ def test_set_core_property(env): _set_value('core.reporting', 'false', env) +def test_url_validation(env): + key = 'core.dcos_url' + default_value = 'http://172.17.8.101' + + _set_value(key, 'http://localhost', env) + _set_value(key, 'https://localhost', env) + _set_value(key, 'http://dcos-1234', env) + _set_value(key, 'http://dcos-1234.mydomain.com', env) + + _set_value(key, 'http://localhost:5050', env) + _set_value(key, 'https://localhost:5050', env) + _set_value(key, 'http://mesos-1234:5050', env) + _set_value(key, 'http://mesos-1234.mydomain.com:5050', env) + + _set_value(key, 'http://localhost:8080', env) + _set_value(key, 'https://localhost:8080', env) + _set_value(key, 'http://marathon-1234:8080', env) + _set_value(key, 'http://marathon-1234.mydomain.com:5050', env) + + _set_value(key, default_value, env) + + +def test_append_url_validation(env): + default_value = ('["https://github.com/mesosphere/universe/archive/' + 'version-1.x.zip"]') + + _set_value('package.sources', '[]', env) + _append_value( + 'package.sources', + 'https://github.com/mesosphere/universe/archive/version-1.x.zip', + env) + _append_value( + 'package.sources', + 'git@github.com:mesosphere/test.git', + env) + _append_value( + 'package.sources', + 'https://github.com/mesosphere/test.git', + env) + _append_value( + 'package.sources', + 'file://some-domain.com/path/to/file.extension', + env) + _append_value( + 'package.sources', + 'file:///path/to/file.extension', + env) + _set_value('package.sources', default_value, env) + + +def test_prepend_url_validation(env): + default_value = ('["https://github.com/mesosphere/universe/archive/' + 'version-1.x.zip"]') + + _set_value('package.sources', '[]', env) + _prepend_value( + 'package.sources', + 'https://github.com/mesosphere/universe/archive/version-1.x.zip', + env) + _prepend_value( + 'package.sources', + 'git@github.com:mesosphere/test.git', + env) + _prepend_value( + 'package.sources', + 'https://github.com/mesosphere/test.git', + env) + _prepend_value( + 'package.sources', + 'file://some-domain.com/path/to/file.extension', + env) + _prepend_value( + 'package.sources', + 'file:///path/to/file.extension', + env) + _set_value('package.sources', default_value, env) + + +def test_fail_url_validation(env): + _fail_url_validation('set', 'core.dcos_url', 'http://bad_domain/', env) + + +def test_bad_port_fail_url_validation(env): + _fail_url_validation('set', 'core.dcos_url', + 'http://localhost:bad_port/', env) + + +def test_append_fail_url_validation(env): + _fail_url_validation('append', 'package.sources', 'bad_url', env) + + +def test_prepend_fail_url_validation(env): + _fail_url_validation('prepend', 'package.sources', 'bad_url', env) + + +def _fail_url_validation(command, key, value, env): + returncode_, stdout_, stderr_ = exec_command( + ['dcos', 'config', command, key, value], env=env) + + assert returncode_ == 1 + assert stdout_ == b'' + assert stderr_.startswith(str( + 'Error: {!r} does not match'.format(value)).encode('utf-8')) + + def _set_value(key, value, env): assert_command( ['dcos', 'config', 'set', key, value],