diff --git a/dcos/cli/config.py b/dcos/cli/config.py index 1602c9d..3465730 100644 --- a/dcos/cli/config.py +++ b/dcos/cli/config.py @@ -46,6 +46,12 @@ def main(): def _save_config_file(config_path, toml_config): + """Save dictionary as TOML file + + :param config_path: Path to configuration file. + :type config_path: str or unicode + """ + serial = toml.dumps(toml_config) with open(config_path, 'w') as config_file: config_file.write(serial) diff --git a/dcos/cli/dcos.py b/dcos/cli/dcos.py index 5e3d894..a1b07e0 100644 --- a/dcos/cli/dcos.py +++ b/dcos/cli/dcos.py @@ -44,6 +44,13 @@ def main(): def _list_external_subcommands(dcos_path): + """List external subcommands + + :param dcos_path: Path to the directory where the dcos cli is installed + :type dcos_path: str + :returns: List of subcommands + :rtype: list of str + """ prefix = 'dcos-' return [filename[len(prefix):] @@ -59,6 +66,13 @@ def _list_external_subcommands(dcos_path): def _external_command_documentation(commands): + """Gather sub-command summary + + :param commands: List of subcommand + :type comands: list of str + :returns: Returns a list of subcommand and their summary + :rtype: list of (str, str) + """ def info(commnand): return subprocess.check_output( ['dcos-{}'.format(command), command, 'info']) @@ -67,6 +81,12 @@ def _external_command_documentation(commands): def _is_valid_configuration(): + """Validates running environment + + :returns: True if the environment is configure correctly, False otherwise. + :rtype: bool + """ + dcos_path = os.environ.get(constants.DCOS_PATH_ENV) if dcos_path is None: msg = 'Environment variable {!r} not set to the DCOS CLI path.' diff --git a/dcos/cli/marathon.py b/dcos/cli/marathon.py index 95b1ca9..a001edd 100644 --- a/dcos/cli/marathon.py +++ b/dcos/cli/marathon.py @@ -35,11 +35,26 @@ def main(): def _info(): + """Print marathon cli information + + :returns: Process status + :rtype: int + """ + print('Deploy and manage containers for Mesos') return 0 def _start(app_resource_path, config): + """Starts an application with Marathon + + :param app_resource_path: Path to the application resource + :type app_resource_path: str + :param config: Configuration dictionary + :type config: config.Toml + :returns: Process status + :rtype: int + """ client = marathon.Client(config['marathon.host'], config['marathon.port']) with open(app_resource_path) as app_resource_file: diff --git a/dcos/config.py b/dcos/config.py index ddff133..cfab411 100644 --- a/dcos/config.py +++ b/dcos/config.py @@ -10,12 +10,21 @@ class Toml(collections.MutableMapping): def __init__(self, dictionary): """Constructs interface for managing configurations - :config_path: (string) Path to the TOML configuration file - + :param dictionary: Configuration dictionary + :type dictionary: dict """ + self._dictionary = dictionary def __getitem__(self, path): + """Get the value for a path + + :param path: Path to the value. E.g. 'path.to.value' + :type path: str + :returns: Value stored at the given path + :rtype: double, int, str, list or dict + """ + config = self._dictionary for section in path.split('.'): @@ -27,12 +36,32 @@ class Toml(collections.MutableMapping): return config def __iter__(self): + """Returns iterator + + :returns: Dictionary iterator + :rtype: iterator + """ + return iter(self._dictionary) def __len__(self): + """Length of the toml configuration + + :returns: The length of the dictionary + :rtype: int + """ + return len(self._dictionary) def __setitem__(self, path, value): + """Set the path to a value + + :param path: Path to set + :type path: str + :param value: Value to store + :type value: double, int, str, list or dict + """ + config = self._dictionary sections = path.split('.') @@ -42,6 +71,11 @@ class Toml(collections.MutableMapping): config[sections[-1]] = value def __delitem__(self, path): + """Delete value stored at path + + :param path: Path to delete + :type path: str + """ config = self._dictionary sections = path.split('.') @@ -52,5 +86,13 @@ class Toml(collections.MutableMapping): @classmethod def load_from_path(class_, path): + """Loads a TOML file from the path + + :param path: Path to the TOML file + :type path: str + :returns: Dictionary for the configuration file + :rtype: Toml + """ + with open(path) as config_file: return Toml(toml.loads(config_file.read())) diff --git a/dcos/errors.py b/dcos/errors.py index e62e742..c8df35e 100644 --- a/dcos/errors.py +++ b/dcos/errors.py @@ -5,4 +5,10 @@ class Error(object): @abc.abstractmethod def error(self): + """Creates an error message + + :returns: The error message + :rtype: str + """ + raise NotImplementedError diff --git a/dcos/marathon.py b/dcos/marathon.py index f089bff..6113084 100644 --- a/dcos/marathon.py +++ b/dcos/marathon.py @@ -9,15 +9,25 @@ class Client(object): def __init__(self, host, port): """Constructs interface for talking Marathon. - :param host: (string) Host for the Marathon server. - :param port: (int) Port for the Marathon server. - + :param host: Host for the Marathon server. + :type host: str + :param port: Port for the Marathon server. + :type port: int """ + self._url_pattern = "http://{host}:{port}/{path}" self._host = host self._port = port def _create_url(self, path): + """Creates the url from the provided path + + :param path: Url path + :type path: str + :return: Constructed url + :rtype: str + """ + return self._url_pattern.format( host=self._host, port=self._port, @@ -26,9 +36,12 @@ class Client(object): def start_app(self, app_resource): """Create and start a new application - :param app_resource: (dict) Application resource - + :param app_resource: Application resource + :type app_resource: dict, bytes, or file + :returns: Status of trying to start the application + :rtype: (bool, Error) """ + url = self._create_url('v2/apps') response = requests.post(url, data=app_resource) @@ -44,7 +57,19 @@ class Client(object): class Error(errors.Error): def __init__(self, message): + """Constructs error for Marathon calls + + :param message: Error message + :type message: str + """ + self._message = message def error(self): + """Return error message + + :returns: The error message + :rtype: str + """ + return self._message diff --git a/dcos/options.py b/dcos/options.py index 3a60d26..2c762ae 100644 --- a/dcos/options.py +++ b/dcos/options.py @@ -1,4 +1,14 @@ def extend_usage_docopt(doc, command_summaries): + """Extends usage information with sub-command summaries + + :param doc: Usage documentation + :type doc: str + :param command_summaries: Commands and their summaries + :type command_summaries: list of (str, str) + :returns: Usage documetation with the sub-command summaries + :rtype: str + """ + doc += '\nThe dcos commands are:' for command, summary in command_summaries: doc += '\n\t{:15}\t{}'.format(command, summary.strip())