From 8cad17dca050dd638af1abc2b75106f466afaaea Mon Sep 17 00:00:00 2001 From: Kyryl Truskovskyi Date: Thu, 20 Aug 2015 17:30:07 +0300 Subject: [PATCH] [ADD] DCOS-1323 [FIX] add new line [FIX] change check --- cli/dcoscli/common.py | 28 ++++++++ cli/dcoscli/help/main.py | 82 ++++++++++++++++++------ cli/tests/data/help/config.txt | 22 +++++++ cli/tests/data/help/marathon.txt | 99 +++++++++++++++++++++++++++++ cli/tests/data/help/node.txt | 24 +++++++ cli/tests/data/help/package.txt | 76 ++++++++++++++++++++++ cli/tests/data/help/service.txt | 37 +++++++++++ cli/tests/data/help/task.txt | 24 +++++++ cli/tests/integrations/test_help.py | 39 +++++++++++- 9 files changed, 409 insertions(+), 22 deletions(-) create mode 100644 cli/dcoscli/common.py create mode 100644 cli/tests/data/help/config.txt create mode 100644 cli/tests/data/help/marathon.txt create mode 100644 cli/tests/data/help/node.txt create mode 100644 cli/tests/data/help/package.txt create mode 100644 cli/tests/data/help/service.txt create mode 100644 cli/tests/data/help/task.txt diff --git a/cli/dcoscli/common.py b/cli/dcoscli/common.py new file mode 100644 index 0000000..db0f3c1 --- /dev/null +++ b/cli/dcoscli/common.py @@ -0,0 +1,28 @@ +import subprocess + + +def exec_command(cmd, env=None, stdin=None): + """Execute CLI command + + :param cmd: Program and arguments + :type cmd: [str] + :param env: Environment variables + :type env: dict + :param stdin: File to use for stdin + :type stdin: file + :returns: A tuple with the returncode, stdout and stderr + :rtype: (int, bytes, bytes) + """ + + process = subprocess.Popen( + cmd, + stdin=stdin, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env=env) + + # This is needed to get rid of '\r' from Windows's lines endings. + stdout, stderr = [std_stream.replace(b'\r', b'') + for std_stream in process.communicate()] + + return (process.returncode, stdout, stderr) diff --git a/cli/dcoscli/help/main.py b/cli/dcoscli/help/main.py index ac1493c..57cd6f8 100644 --- a/cli/dcoscli/help/main.py +++ b/cli/dcoscli/help/main.py @@ -1,8 +1,9 @@ """Display command line usage information Usage: - dcos help --info dcos help + dcos help --info + dcos help Options: --help Show this screen @@ -15,6 +16,7 @@ import docopt from concurrent.futures import ThreadPoolExecutor from dcos import cmds, emitting, options, subcommand, util from dcos.errors import DCOSException +from dcoscli.common import exec_command from dcoscli.main import decorate_docopt_usage emitter = emitting.FlatEmitter() @@ -47,34 +49,72 @@ def _cmds(): """ return [ + cmds.Command( + hierarchy=['help', '--info'], + arg_keys=[], + function=_info), + cmds.Command( hierarchy=['help'], - arg_keys=['--info'], + arg_keys=[''], function=_help), ] -def _help(show_info): - if show_info: - emitter.publish(__doc__.split('\n')[0]) +def _info(): + """ + :returns: process return code + :rtype: int + """ + + emitter.publish(__doc__.split('\n')[0]) + return 0 + + +def _help(command): + """ + :param command: the command name for which you want to see a help + :type command: str + :returns: process return code + :rtype: int + """ + + if command is not None: + _help_command(command) + else: + directory = util.dcos_path() + logger.debug("DCOS Path: {!r}".format(directory)) + + paths = subcommand.list_paths() + with ThreadPoolExecutor(max_workers=len(paths)) as executor: + results = executor.map(subcommand.documentation, paths) + commands_message = options\ + .make_command_summary_string(sorted(results)) + + emitter.publish( + "Command line utility for the Mesosphere Datacenter Operating\n" + "System (DCOS). The Mesosphere DCOS is a distributed operating\n" + "system built around Apache Mesos. This utility provides tools\n" + "for easy management of a DCOS installation.\n") + emitter.publish("Available DCOS commands:") + emitter.publish(commands_message) + emitter.publish( + "\nGet detailed command description with 'dcos --help'.") + return 0 - directory = util.dcos_path() - logger.debug("DCOS Path: {!r}".format(directory)) - paths = subcommand.list_paths() - with ThreadPoolExecutor(max_workers=len(paths)) as executor: - results = executor.map(subcommand.documentation, paths) - commands_message = options.make_command_summary_string(sorted(results)) - - emitter.publish( - "Command line utility for the Mesosphere Datacenter Operating\n" - "System (DCOS). The Mesosphere DCOS is a distributed operating\n" - "system built around Apache Mesos. This utility provides tools\n" - "for easy management of a DCOS installation.\n") - emitter.publish("Available DCOS commands:") - emitter.publish(commands_message) - emitter.publish( - "\nGet detailed command description with 'dcos --help'.") +def _help_command(command): + """ + :param command: the command name for which you want to see a help + :type command: str + :returns: process return code + :rtype: int + """ + returncode, stdout, stderr = exec_command(['dcos', command, '--help']) + if returncode == 1: + emitter.publish(stderr.decode("utf-8")) + return 1 + emitter.publish(stdout.decode("utf-8")) return 0 diff --git a/cli/tests/data/help/config.txt b/cli/tests/data/help/config.txt new file mode 100644 index 0000000..59ae38f --- /dev/null +++ b/cli/tests/data/help/config.txt @@ -0,0 +1,22 @@ +Get and set DCOS CLI configuration properties + +Usage: + dcos config --info + dcos config append + dcos config prepend + dcos config set + dcos config show [] + dcos config unset [--index=] + dcos config validate + +Options: + -h, --help Show this screen + --info Show a short description of this subcommand + --version Show version + --index= Index into the list. The first element in the list has an + index of zero + +Positional Arguments: + The name of the property + The value of the property + diff --git a/cli/tests/data/help/marathon.txt b/cli/tests/data/help/marathon.txt new file mode 100644 index 0000000..dba5e17 --- /dev/null +++ b/cli/tests/data/help/marathon.txt @@ -0,0 +1,99 @@ +Deploy and manage applications on the DCOS + +Usage: + dcos marathon --config-schema + dcos marathon --info + dcos marathon about + dcos marathon app add [] + dcos marathon app list [--json] + dcos marathon app remove [--force] + dcos marathon app restart [--force] + dcos marathon app show [--app-version=] + dcos marathon app start [--force] [] + dcos marathon app stop [--force] + dcos marathon app update [--force] [...] + dcos marathon app version list [--max-count=] + dcos marathon deployment list [--json ] + dcos marathon deployment rollback + dcos marathon deployment stop + dcos marathon deployment watch [--max-count=] + [--interval=] + dcos marathon task list [--json ] + dcos marathon task show + dcos marathon group add [] + dcos marathon group list [--json] + dcos marathon group show [--group-version=] + dcos marathon group remove [--force] + dcos marathon group update [--force] [...] + +Options: + -h, --help Show this screen + + --info Show a short description of this + subcommand + + --json Print json-formatted tasks + + --version Show version + + --force This flag disable checks in Marathon + during update operations + + --app-version= This flag specifies the application + version to use for the command. The + application version () can be + specified as an absolute value or as + relative value. Absolute version values + must be in ISO8601 date format. Relative + values must be specified as a negative + integer and they represent the version + from the currently deployed application + definition + + --group-version= This flag specifies the group version to + use for the command. The group version + () can be specified as an + absolute value or as relative value. + Absolute version values must be in ISO8601 + date format. Relative values must be + specified as a negative integer and they + represent the version from the currently + deployed group definition + + --config-schema Show the configuration schema for the + Marathon subcommand + + --max-count= Maximum number of entries to try to fetch + and return + + --interval= Number of seconds to wait between actions + +Positional Arguments: + The application id + + Path to a file or HTTP(S) URL containing + the app's JSON definition. If omitted, + the definition is read from stdin. For a + detailed description see + (https://mesosphere.github.io/ + marathon/docs/rest-api.html#post-/v2/apps). + + The deployment id + + The group id + + Path to a file or HTTP(S) URL containing + the group's JSON definition. If omitted, + the definition is read from stdin. For a + detailed description see + (https://mesosphere.github.io/ + marathon/docs/rest-api.html#post-/v2/groups). + + The number of instances to start + + Must be of the format =. E.g. + cpus=2.0. If omitted, properties are read from + stdin. + + The task id + diff --git a/cli/tests/data/help/node.txt b/cli/tests/data/help/node.txt new file mode 100644 index 0000000..c691b7e --- /dev/null +++ b/cli/tests/data/help/node.txt @@ -0,0 +1,24 @@ +Manage DCOS nodes + +Usage: + dcos node --info + dcos node [--json] + dcos node log [--follow --lines=N --master --slave=] + dcos node ssh [--option SSHOPT=VAL ...] + [--config-file=] + [--user=] + (--master | --slave=) + +Options: + -h, --help Show this screen + --info Show a short description of this subcommand + --json Print json-formatted nodes + --follow Print data as the file grows + --lines=N Print the last N lines [default: 10] + --master Access the leading master + --slave= Access the slave with the provided ID + --option SSHOPT=VAL SSH option (see `man ssh_config`) + --config-file= Path to SSH config file + --user= SSH user [default: core] + --version Show version + diff --git a/cli/tests/data/help/package.txt b/cli/tests/data/help/package.txt new file mode 100644 index 0000000..e59725f --- /dev/null +++ b/cli/tests/data/help/package.txt @@ -0,0 +1,76 @@ +Install and manage DCOS packages + +Usage: + dcos package --config-schema + dcos package --info + dcos package describe [--app --cli --config] + [--render] + [--package-versions] + [--options=] + [--package-version=] + + dcos package install [--cli | [--app --app-id=]] + [--package-version=] + [--options=] [--yes] + dcos package list [--json --endpoints --app-id= ] + dcos package search [--json ] + dcos package sources + dcos package uninstall [--cli | [--app --app-id= --all]] + + dcos package update [--validate] + +Options: + --all Apply the operation to all matching packages + + --app Apply the operation only to the package's + Marathon application + + --app-id= The application id + + --cli Apply the operation only to the package's CLI + command + + --config Print the package's config.json, which contains + the configurable properties for marathon.json + and command.json + + -h, --help Show this screen + + --info Show a short description of this subcommand + + --options= Path to a JSON file containing package + installation options + + --package-version= Package version to install + + --package-versions Print all versions for this package + + --render Render the package's marathon.json or + command.json template with the values from + config.json and --options. If not provided, + print the raw templates. + + --validate Validate package content when updating sources + + --version Show version + + --yes Assume "yes" is the answer to all prompts and + run non-interactively + +Configuration: + [package] + # Path to the local package cache. + cache_dir = "/var/dcos/cache" + + # List of package sources, in search order. + # + # Three protocols are supported: + # - Local file + # - HTTPS + # - Git + sources = [ + "file:///Users/me/test-registry", + "https://my.org/registry", + "git://github.com/mesosphere/universe.git" + ] + diff --git a/cli/tests/data/help/service.txt b/cli/tests/data/help/service.txt new file mode 100644 index 0000000..53aead0 --- /dev/null +++ b/cli/tests/data/help/service.txt @@ -0,0 +1,37 @@ +Manage DCOS services + +Usage: + dcos service --info + dcos service [--inactive --json] + dcos service log [--follow --lines=N --ssh-config-file=] + [] + dcos service shutdown + +Options: + -h, --help Show this screen + + --info Show a short description of this subcommand + + --ssh-config-file= Path to SSH config file. Used to access + marathon logs. + + --follow Print data as the file grows + + --inactive Show inactive services in addition to active + ones. Inactive services are those that have + been disconnected from master, but haven't yet + reached their failover timeout. + + --json Print json-formatted services + + --lines=N Print the last N lines [default: 10] + + --version Show version + +Positional Arguments: + Output this file. [default: stdout] + + The DCOS Service name. + + The DCOS Service ID + diff --git a/cli/tests/data/help/task.txt b/cli/tests/data/help/task.txt new file mode 100644 index 0000000..ca0f359 --- /dev/null +++ b/cli/tests/data/help/task.txt @@ -0,0 +1,24 @@ +Manage DCOS tasks + +Usage: + dcos task --info + dcos task [--completed --json ] + dcos task log [--completed --follow --lines=N] [] + dcos task ls [--long] [] + +Options: + -h, --help Show this screen + --info Show a short description of this subcommand + --completed Include completed tasks as well + --follow Print data as the file grows + --json Print json-formatted tasks + --lines=N Print the last N lines [default: 10] + --long Use a long listing format + --version Show version + +Positional Arguments: + Print this file. [default: stdout] + List this directory. [default: '.'] + Only match tasks whose ID matches . may be + a substring of the ID, or a unix glob pattern. + diff --git a/cli/tests/integrations/test_help.py b/cli/tests/integrations/test_help.py index 94d1d28..e24e7df 100644 --- a/cli/tests/integrations/test_help.py +++ b/cli/tests/integrations/test_help.py @@ -5,8 +5,9 @@ def test_help(): stdout = b"""Display command line usage information Usage: - dcos help --info dcos help + dcos help --info + dcos help Options: --help Show this screen @@ -49,3 +50,39 @@ Get detailed command description with 'dcos --help'. assert_command(['dcos', 'help'], stdout=stdout) + + +def test_help_config(): + with open('tests/data/help/config.txt') as content: + assert_command(['dcos', 'help', 'config'], + stdout=content.read().encode('utf-8')) + + +def test_help_marathon(): + with open('tests/data/help/marathon.txt') as content: + assert_command(['dcos', 'help', 'marathon'], + stdout=content.read().encode('utf-8')) + + +def test_help_node(): + with open('tests/data/help/node.txt') as content: + assert_command(['dcos', 'help', 'node'], + stdout=content.read().encode('utf-8')) + + +def test_help_package(): + with open('tests/data/help/package.txt') as content: + assert_command(['dcos', 'help', 'package'], + stdout=content.read().encode('utf-8')) + + +def test_help_service(): + with open('tests/data/help/service.txt') as content: + assert_command(['dcos', 'help', 'service'], + stdout=content.read().encode('utf-8')) + + +def test_help_task(): + with open('tests/data/help/task.txt') as content: + assert_command(['dcos', 'help', 'task'], + stdout=content.read().encode('utf-8'))