Removed dependency on DCOS_CONFIG env var
This commit is contained in:
13
README.rst
13
README.rst
@@ -1,6 +1,6 @@
|
||||
DCOS Command Line Interface
|
||||
===========================
|
||||
The DCOS Command Line Interface (CLI) is a cross-platform command line utility
|
||||
The DCOS Command Line Interface (CLI) is a cross-platform command line utility
|
||||
that provides a user-friendly yet powerful way to manage DCOS installations.
|
||||
|
||||
Installation and Usage
|
||||
@@ -30,7 +30,7 @@ The example below installs every package available in the DCOS repository::
|
||||
Using the CLI without DCOS
|
||||
--------------------------
|
||||
|
||||
You may optionally configure the DCOS CLI to work with open source Mesos and
|
||||
You may optionally configure the DCOS CLI to work with open source Mesos and
|
||||
Marathon_ by setting the following properties::
|
||||
dcos config set core.mesos_master_url http://<mesos-master-host>:5050
|
||||
dcos config set marathon.url http://<marathon-host>:8080
|
||||
@@ -112,12 +112,9 @@ Running
|
||||
Tox will run unit and integration tests in both Python environments using a
|
||||
temporarily created virtualenv.
|
||||
|
||||
You should ensure :code:`DCOS_CONFIG` is set and that the config file points
|
||||
to the Marathon instance you want to use for integration tests. If you're
|
||||
happy to use the default test configuration which assumes there is a Marathon
|
||||
instance running on localhost, set :code:`DCOS_CONFIG` as follows::
|
||||
|
||||
export DCOS_CONFIG=$(pwd)/tests/data/dcos.toml
|
||||
You can set :code:`DCOS_CONFIG` to a config file that points to a DCOS
|
||||
cluster you want to use for integration tests. This defaults to
|
||||
:code:`~/.dcos/dcos.toml`
|
||||
|
||||
If you are testing against the DCOS Image you can configure the URL to the
|
||||
Exhibitor::
|
||||
|
||||
@@ -6,12 +6,8 @@ else
|
||||
BIN_DIR=$PWD/bin
|
||||
fi
|
||||
|
||||
# real, absolute path to BIN_DIR
|
||||
FULL_BIN_PATH=$(python -c "import os; print(os.path.realpath('$BIN_DIR'))")
|
||||
|
||||
# ensure BIN_DIR is prepended to PATH
|
||||
expr "$PATH" : "${FULL_BIN_PATH}.*" > /dev/null || export PATH=$FULL_BIN_PATH:$PATH
|
||||
export DCOS_CONFIG=~/.dcos/dcos.toml
|
||||
|
||||
if [ ! -f "$DCOS_CONFIG" ]; then
|
||||
mkdir -p $(dirname "$DCOS_CONFIG")
|
||||
touch "$DCOS_CONFIG"
|
||||
fi
|
||||
|
||||
@@ -24,15 +24,12 @@ Positional Arguments:
|
||||
import collections
|
||||
import copy
|
||||
import json
|
||||
import os
|
||||
|
||||
import dcoscli
|
||||
import docopt
|
||||
import pkg_resources
|
||||
import six
|
||||
import toml
|
||||
from dcos import (cmds, config, constants, emitting, http, jsonitem,
|
||||
subcommand, util)
|
||||
from dcos import cmds, config, emitting, http, jsonitem, subcommand, util
|
||||
from dcos.errors import DCOSException
|
||||
from dcoscli import analytics
|
||||
|
||||
@@ -153,7 +150,7 @@ def _set(name, value):
|
||||
:rtype: int
|
||||
"""
|
||||
|
||||
config_path, toml_config = _load_config()
|
||||
toml_config = util.get_config(True)
|
||||
|
||||
section, subkey = _split_key(name)
|
||||
|
||||
@@ -172,7 +169,7 @@ def _set(name, value):
|
||||
|
||||
_check_config(toml_config_pre, toml_config)
|
||||
|
||||
_save_config_file(config_path, toml_config)
|
||||
config.save(toml_config)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -182,7 +179,7 @@ def _append(name, value):
|
||||
:rtype: int
|
||||
"""
|
||||
|
||||
config_path, toml_config = _load_config()
|
||||
toml_config = util.get_config(True)
|
||||
|
||||
python_value = _parse_array_item(name, value)
|
||||
toml_config_pre = copy.deepcopy(toml_config)
|
||||
@@ -194,7 +191,7 @@ def _append(name, value):
|
||||
|
||||
_check_config(toml_config_pre, toml_config)
|
||||
|
||||
_save_config_file(config_path, toml_config)
|
||||
config.save(toml_config)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -204,7 +201,7 @@ def _prepend(name, value):
|
||||
:rtype: int
|
||||
"""
|
||||
|
||||
config_path, toml_config = _load_config()
|
||||
toml_config = util.get_config(True)
|
||||
|
||||
python_value = _parse_array_item(name, value)
|
||||
|
||||
@@ -215,7 +212,7 @@ def _prepend(name, value):
|
||||
toml_config[name] = python_value + toml_config.get(name, [])
|
||||
_check_config(toml_config_pre, toml_config)
|
||||
|
||||
_save_config_file(config_path, toml_config)
|
||||
config.save(toml_config)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -225,7 +222,7 @@ def _unset(name, index):
|
||||
:rtype: int
|
||||
"""
|
||||
|
||||
config_path, toml_config = _load_config()
|
||||
toml_config = util.get_config(True)
|
||||
toml_config_pre = copy.deepcopy(toml_config)
|
||||
section = name.split(".", 1)[0]
|
||||
if section not in toml_config_pre._dictionary:
|
||||
@@ -251,7 +248,7 @@ def _unset(name, index):
|
||||
raise DCOSException(
|
||||
'Unsetting based on an index is only supported for lists')
|
||||
|
||||
_save_config_file(config_path, toml_config)
|
||||
config.save(toml_config)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -261,7 +258,7 @@ def _show(name):
|
||||
:rtype: int
|
||||
"""
|
||||
|
||||
_, toml_config = _load_config()
|
||||
toml_config = util.get_config(True)
|
||||
|
||||
if name is not None:
|
||||
value = toml_config.get(name)
|
||||
@@ -285,7 +282,7 @@ def _validate():
|
||||
:rtype: int
|
||||
"""
|
||||
|
||||
_, toml_config = _load_config()
|
||||
toml_config = util.get_config(True)
|
||||
|
||||
errs = util.validate_json(toml_config._dictionary,
|
||||
_generate_root_schema(toml_config))
|
||||
@@ -338,29 +335,6 @@ def _generate_choice_msg(name, value):
|
||||
return message
|
||||
|
||||
|
||||
def _load_config():
|
||||
"""
|
||||
:returns: process status
|
||||
:rtype: int
|
||||
"""
|
||||
|
||||
config_path = os.environ[constants.DCOS_CONFIG_ENV]
|
||||
return (config_path, config.mutable_load_from_path(config_path))
|
||||
|
||||
|
||||
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
|
||||
"""
|
||||
|
||||
serial = toml.dumps(toml_config._dictionary)
|
||||
with util.open_file(config_path, 'w') as config_file:
|
||||
config_file.write(serial)
|
||||
|
||||
|
||||
def _get_config_schema(command):
|
||||
"""
|
||||
:param command: the subcommand name
|
||||
|
||||
@@ -29,6 +29,7 @@ Environment Variables:
|
||||
|
||||
DCOS_CONFIG This environment variable points to the
|
||||
location of the DCOS configuration file.
|
||||
[default: ~/.dcos/dcos.toml]
|
||||
|
||||
DCOS_DEBUG If set then enable further debug messages which
|
||||
are sent to stdout.
|
||||
@@ -59,9 +60,6 @@ def main():
|
||||
def _main():
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
|
||||
if not _is_valid_configuration():
|
||||
return 1
|
||||
|
||||
args = docopt.docopt(
|
||||
__doc__,
|
||||
version='dcos version {}'.format(dcoscli.version),
|
||||
@@ -128,27 +126,6 @@ def _config_debug_environ(is_debug):
|
||||
os.environ.pop(constants.DCOS_DEBUG_ENV, None)
|
||||
|
||||
|
||||
def _is_valid_configuration():
|
||||
"""Validates running environment
|
||||
|
||||
:returns: True if the environment is configure correctly; False otherwise.
|
||||
:rtype: bool
|
||||
"""
|
||||
|
||||
dcos_config = os.environ.get(constants.DCOS_CONFIG_ENV)
|
||||
if dcos_config is None:
|
||||
msg = 'Environment variable {!r} must be set to the DCOS config file.'
|
||||
emitter.publish(msg.format(constants.DCOS_CONFIG_ENV))
|
||||
return False
|
||||
|
||||
if not os.path.isfile(dcos_config):
|
||||
msg = 'Environment variable {!r} maps to {!r} and it is not a file.'
|
||||
emitter.publish(msg.format(constants.DCOS_CONFIG_ENV, dcos_config))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def signal_handler(signal, frame):
|
||||
emitter.publish(
|
||||
errors.DefaultError("User interrupted command with Ctrl-C"))
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
import os
|
||||
|
||||
from dcos import constants
|
||||
|
||||
from .common import assert_command, exec_command
|
||||
|
||||
|
||||
@@ -62,6 +58,7 @@ Environment Variables:
|
||||
|
||||
DCOS_CONFIG This environment variable points to the
|
||||
location of the DCOS configuration file.
|
||||
[default: ~/.dcos/dcos.toml]
|
||||
|
||||
DCOS_DEBUG If set then enable further debug messages which
|
||||
are sent to stdout.
|
||||
@@ -76,38 +73,6 @@ def test_version():
|
||||
stdout=b'dcos version SNAPSHOT\n')
|
||||
|
||||
|
||||
def test_missing_dcos_config():
|
||||
env = os.environ.copy()
|
||||
del env['DCOS_CONFIG']
|
||||
env.update({
|
||||
constants.PATH_ENV: os.environ[constants.PATH_ENV],
|
||||
})
|
||||
|
||||
stdout = (b"Environment variable 'DCOS_CONFIG' must be set "
|
||||
b"to the DCOS config file.\n")
|
||||
|
||||
assert_command(['dcos'],
|
||||
stdout=stdout,
|
||||
returncode=1,
|
||||
env=env)
|
||||
|
||||
|
||||
def test_dcos_config_not_a_file():
|
||||
env = os.environ.copy()
|
||||
env.update({
|
||||
constants.PATH_ENV: os.environ[constants.PATH_ENV],
|
||||
'DCOS_CONFIG': 'missing/file',
|
||||
})
|
||||
|
||||
stdout = (b"Environment variable 'DCOS_CONFIG' maps to "
|
||||
b"'missing/file' and it is not a file.\n")
|
||||
|
||||
assert_command(['dcos'],
|
||||
returncode=1,
|
||||
stdout=stdout,
|
||||
env=env)
|
||||
|
||||
|
||||
def test_log_level_flag():
|
||||
returncode, stdout, stderr = exec_command(
|
||||
['dcos', '--log-level=info', 'config', '--info'])
|
||||
|
||||
12
dcos/auth.py
12
dcos/auth.py
@@ -1,11 +1,9 @@
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import uuid
|
||||
|
||||
import pkg_resources
|
||||
import toml
|
||||
from dcos import config, constants, emitting, errors, http, jsonitem, util
|
||||
from dcos import config, emitting, errors, http, jsonitem, util
|
||||
from dcos.errors import DCOSException
|
||||
from six import iteritems
|
||||
|
||||
@@ -124,8 +122,7 @@ def _save_auth_keys(key_dict):
|
||||
:rtype: None
|
||||
"""
|
||||
|
||||
config_path = os.environ[constants.DCOS_CONFIG_ENV]
|
||||
toml_config = config.mutable_load_from_path(config_path)
|
||||
toml_config = util.get_config(True)
|
||||
|
||||
section = 'core'
|
||||
config_schema = json.loads(
|
||||
@@ -137,8 +134,5 @@ def _save_auth_keys(key_dict):
|
||||
name = '{}.{}'.format(section, k)
|
||||
toml_config[name] = python_value
|
||||
|
||||
serial = toml.dumps(toml_config._dictionary)
|
||||
with util.open_file(config_path, 'w') as config_file:
|
||||
config_file.write(serial)
|
||||
|
||||
config.save(toml_config)
|
||||
return None
|
||||
|
||||
@@ -4,30 +4,33 @@ import toml
|
||||
from dcos import util
|
||||
|
||||
|
||||
def mutable_load_from_path(path):
|
||||
"""Loads a TOML file from the path
|
||||
|
||||
:param path: Path to the TOML file
|
||||
:type path: str
|
||||
:returns: Mutable map for the configuration file
|
||||
:rtype: MutableToml
|
||||
"""
|
||||
|
||||
with util.open_file(path) as config_file:
|
||||
return MutableToml(toml.loads(config_file.read()))
|
||||
|
||||
|
||||
def load_from_path(path):
|
||||
def load_from_path(path, mutable=False):
|
||||
"""Loads a TOML file from the path
|
||||
|
||||
:param path: Path to the TOML file
|
||||
:type path: str
|
||||
:param mutable: True if the returned Toml object should be mutable
|
||||
:type mutable: boolean
|
||||
:returns: Map for the configuration file
|
||||
:rtype: Toml
|
||||
:rtype: Toml | MutableToml
|
||||
"""
|
||||
|
||||
with util.open_file(path) as config_file:
|
||||
return Toml(toml.loads(config_file.read()))
|
||||
util.ensure_file_exists(path)
|
||||
with util.open_file(path, 'r') as config_file:
|
||||
toml_obj = toml.loads(config_file.read())
|
||||
return (MutableToml if mutable else Toml)(toml_obj)
|
||||
|
||||
|
||||
def save(toml_config):
|
||||
"""
|
||||
:param toml_config: TOML configuration object
|
||||
:type toml_config: MutableToml or Toml
|
||||
"""
|
||||
|
||||
serial = toml.dumps(toml_config._dictionary)
|
||||
path = util.get_config_path()
|
||||
with util.open_file(path, 'w') as config_file:
|
||||
config_file.write(serial)
|
||||
|
||||
|
||||
def _get_path(config, path):
|
||||
|
||||
@@ -275,7 +275,7 @@ def install(pkg, revision, options):
|
||||
"""
|
||||
|
||||
pkg_dir = package_dir(pkg.name())
|
||||
util.ensure_dir(pkg_dir)
|
||||
util.ensure_dir_exists(pkg_dir)
|
||||
|
||||
_write_package_json(pkg, revision)
|
||||
_write_package_revision(pkg, revision)
|
||||
|
||||
45
dcos/util.py
45
dcos/util.py
@@ -74,7 +74,7 @@ def temptext():
|
||||
shutil.rmtree(path, ignore_errors=True)
|
||||
|
||||
|
||||
def ensure_dir(directory):
|
||||
def ensure_dir_exists(directory):
|
||||
"""If `directory` does not exist, create it.
|
||||
|
||||
:param directory: path to the directory
|
||||
@@ -92,6 +92,22 @@ def ensure_dir(directory):
|
||||
'Cannot create directory [{}]: {}'.format(directory, e))
|
||||
|
||||
|
||||
def ensure_file_exists(path):
|
||||
""" Create file if it doesn't exist
|
||||
|
||||
:param path: path of file to create
|
||||
:type path: str
|
||||
:rtype: None
|
||||
"""
|
||||
|
||||
if not os.path.exists(path):
|
||||
try:
|
||||
open(path, 'w').close()
|
||||
except IOError as e:
|
||||
raise DCOSException(
|
||||
'Cannot create file [{}]: {}'.format(path, e))
|
||||
|
||||
|
||||
def read_file(path):
|
||||
"""
|
||||
:param path: path to file
|
||||
@@ -106,17 +122,36 @@ def read_file(path):
|
||||
return file_.read()
|
||||
|
||||
|
||||
def get_config():
|
||||
def get_config_path():
|
||||
""" Returns the path to the DCOS config file.
|
||||
|
||||
:returns: path to the DCOS config file
|
||||
:rtype: str
|
||||
"""
|
||||
|
||||
default = os.path.expanduser(
|
||||
os.path.join("~",
|
||||
constants.DCOS_DIR,
|
||||
'dcos.toml'))
|
||||
|
||||
return os.environ.get(constants.DCOS_CONFIG_ENV, default)
|
||||
|
||||
|
||||
def get_config(mutable=False):
|
||||
""" Returns the DCOS configuration object
|
||||
|
||||
:param mutable: True if the returned Toml object should be mutable
|
||||
:type mutable: boolean
|
||||
:returns: Configuration object
|
||||
:rtype: Toml
|
||||
:rtype: Toml | MutableToml
|
||||
"""
|
||||
|
||||
# avoid circular import
|
||||
from dcos import config
|
||||
|
||||
return config.load_from_path(
|
||||
os.environ[constants.DCOS_CONFIG_ENV])
|
||||
path = get_config_path()
|
||||
|
||||
return config.load_from_path(path, mutable)
|
||||
|
||||
|
||||
def get_config_vals(keys, config=None):
|
||||
|
||||
Reference in New Issue
Block a user