You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by kl...@apache.org on 2017/07/23 23:46:59 UTC

[2/2] mesos git commit: Moved new Mesos CLI to 'src/python/cli_new'.

Moved new Mesos CLI to 'src/python/cli_new'.

This change allows us to have all Python files under
only two directories : 'src/python/' and 'support/'. This
will improve the structure of our Python code in the future
by sharing configuration files and virtual environments.

Review: https://reviews.apache.org/r/60899


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/09fa758b
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/09fa758b
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/09fa758b

Branch: refs/heads/master
Commit: 09fa758b89d3149ae8910d84377a2656064903a6
Parents: 2d19111
Author: Kevin Klues <kl...@gmail.com>
Authored: Sun Jul 23 16:42:55 2017 -0700
Committer: Kevin Klues <kl...@gmail.com>
Committed: Sun Jul 23 16:45:41 2017 -0700

----------------------------------------------------------------------
 src/cli_new/.gitignore                          |   2 -
 src/cli_new/README.md                           |  83 ----
 src/cli_new/activate                            |   4 -
 src/cli_new/bin/main.py                         | 155 -------
 src/cli_new/bin/mesos                           |   6 -
 src/cli_new/bin/mesos-cli-tests                 |   6 -
 src/cli_new/bin/settings.py                     |  47 ---
 src/cli_new/bootstrap                           | 107 -----
 src/cli_new/deactivate                          |   4 -
 src/cli_new/lib/cli/__init__.py                 |  24 --
 src/cli_new/lib/cli/config.py                   |  64 ---
 src/cli_new/lib/cli/docopt.py                   |  90 ----
 src/cli_new/lib/cli/exceptions.py               |  25 --
 src/cli_new/lib/cli/http.py                     |  77 ----
 src/cli_new/lib/cli/plugins/__init__.py         |  22 -
 src/cli_new/lib/cli/plugins/base.py             | 177 --------
 src/cli_new/lib/cli/plugins/config/__init__.py  |  22 -
 src/cli_new/lib/cli/plugins/config/main.py      |  98 -----
 src/cli_new/lib/cli/tests/__init__.py           |  23 -
 src/cli_new/lib/cli/tests/base.py               | 422 ------------------
 src/cli_new/lib/cli/tests/constants.py          |  25 --
 src/cli_new/lib/cli/tests/tests.py              |  65 ---
 src/cli_new/lib/cli/util.py                     | 259 ------------
 src/cli_new/mesos.bash_completion               |  46 --
 src/cli_new/pip-requirements.txt                |  16 -
 src/cli_new/pylint.config                       |  26 --
 src/cli_new/tests/main.py                       |  35 --
 src/python/cli_new/README.md                    |  83 ++++
 src/python/cli_new/activate                     |   4 +
 src/python/cli_new/bin/main.py                  | 155 +++++++
 src/python/cli_new/bin/mesos                    |   6 +
 src/python/cli_new/bin/mesos-cli-tests          |   6 +
 src/python/cli_new/bin/settings.py              |  47 +++
 src/python/cli_new/bootstrap                    | 107 +++++
 src/python/cli_new/deactivate                   |   4 +
 src/python/cli_new/lib/cli/__init__.py          |  24 ++
 src/python/cli_new/lib/cli/config.py            |  64 +++
 src/python/cli_new/lib/cli/docopt.py            |  90 ++++
 src/python/cli_new/lib/cli/exceptions.py        |  25 ++
 src/python/cli_new/lib/cli/http.py              |  77 ++++
 src/python/cli_new/lib/cli/plugins/__init__.py  |  22 +
 src/python/cli_new/lib/cli/plugins/base.py      | 177 ++++++++
 .../cli_new/lib/cli/plugins/config/__init__.py  |  22 +
 .../cli_new/lib/cli/plugins/config/main.py      |  98 +++++
 src/python/cli_new/lib/cli/tests/__init__.py    |  23 +
 src/python/cli_new/lib/cli/tests/base.py        | 423 +++++++++++++++++++
 src/python/cli_new/lib/cli/tests/constants.py   |  25 ++
 src/python/cli_new/lib/cli/tests/tests.py       |  65 +++
 src/python/cli_new/lib/cli/util.py              | 259 ++++++++++++
 src/python/cli_new/mesos.bash_completion        |  46 ++
 src/python/cli_new/pip-requirements.txt         |  16 +
 src/python/cli_new/pylint.config                |  26 ++
 src/python/cli_new/tests/main.py                |  35 ++
 support/mesos-style.py                          |   2 +-
 54 files changed, 1930 insertions(+), 1931 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/.gitignore
----------------------------------------------------------------------
diff --git a/src/cli_new/.gitignore b/src/cli_new/.gitignore
deleted file mode 100644
index 3ce5f74..0000000
--- a/src/cli_new/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-.virtualenv
-*.pyc

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/README.md
----------------------------------------------------------------------
diff --git a/src/cli_new/README.md b/src/cli_new/README.md
deleted file mode 100644
index c5475c7..0000000
--- a/src/cli_new/README.md
+++ /dev/null
@@ -1,83 +0,0 @@
-# Mesos CLI
-
-## Prerequisites
-
-Make sure you have the following prerequisites
-installed on your system before you begin.
-
-```
-python 2.6 or 2.7
-virtualenv
-```
-
-## Getting Started
-
-Once you you have the prerequisites installed, simply
-run the `bootstrap` script from this directory to set
-up a python virtual environment and start running the tool.
-
-```
-$ ./bootstrap
-
-...
-
-Setup complete!
-
-To begin working, simply activate your virtual environment,
-run the CLI, and then deactivate the virtual environment
-when you are done.
-
-    $ source activate
-    $ mesos <command> [<args>...]
-    $ source deactivate
-```
-
-**NOTE:** The virtual environment will also setup bash
-autocomplete for all `mesos` commands.
-
-
-## Running tests
-
-To run the unit tests developed for the Mesos CLI, use
-`mesos-cli-tests`:
-
-```
-$ ./bootstrap
-
-...
-
-Setup complete!
-
-To begin working, simply activate your virtual environment,
-run the CLI, and then deactivate the virtual environment
-when you are done.
-
-    $ source activate
-    $ mesos-cli-tests
-
-Running the Mesos CLI unit tests
-
-...
-
-OK
-```
-
-
-## Setting up your configuration
-
-In order to use this tool, you will need to create a
-configuration file in your home directory under
-`~/.mesos/config.toml`. A template for this config can be
-seen below:
-
-```
-# The `plugins` is an array listing the absolute paths of the
-# plugins you want to add to the CLI.
-plugins = [
-  "</absolute/path/to/plugin-1/directory>",
-  "</absolute/path/to/plugin-2/directory>"
-]
-```
-
-You can override the location of this configuration file using
-the environment variable `MESOS_CLI_CONFIG`.

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/activate
----------------------------------------------------------------------
diff --git a/src/cli_new/activate b/src/cli_new/activate
deleted file mode 100644
index 65df76f..0000000
--- a/src/cli_new/activate
+++ /dev/null
@@ -1,4 +0,0 @@
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-
-source ${DIR}/.virtualenv/bin/activate
-source ${DIR}/.virtualenv/bin/postactivate

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/bin/main.py
----------------------------------------------------------------------
diff --git a/src/cli_new/bin/main.py b/src/cli_new/bin/main.py
deleted file mode 100644
index 5313038..0000000
--- a/src/cli_new/bin/main.py
+++ /dev/null
@@ -1,155 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-This is the main executable of the mesos-cli.
-"""
-
-import sys
-
-import settings
-
-import cli
-
-from cli.docopt import docopt
-from cli.exceptions import CLIException
-
-
-VERSION = "Mesos " + settings.VERSION + " CLI"
-
-SHORT_HELP = "Perform operations on a running Mesos cluster."
-
-USAGE = \
-"""Mesos CLI
-
-Usage:
-  mesos (-h | --help)
-  mesos --version
-  mesos <command> [<args>...]
-
-Options:
-  -h --help  Show this screen.
-  --version  Show version info.
-
-Commands:
-{commands}
-See 'mesos help <command>' for more information on a specific command.
-"""
-
-
-def autocomplete(cmds, plugins, config, argv):
-    """
-    Perform autocomplete for the given input arguments. If not
-    completing a top level command (or "help"), this function passes
-    the arguments down to the appropriate plugins for per-plugin
-    autocompletion.
-    """
-
-    option = "default"
-    current_word = argv[0]
-    argv = argv[1:]
-
-    if len(argv) > 0 and argv[0] == "help":
-        argv = argv[1:]
-
-    comp_words = list(cmds.keys()) + ["help"]
-    comp_words = cli.util.completions(comp_words, current_word, argv)
-    if comp_words != None:
-        return (option, comp_words)
-
-    plugin = cli.util.get_module(plugins, argv[0])
-    plugin_class = getattr(plugin, plugin.PLUGIN_CLASS)
-
-    return plugin_class(settings, config).__autocomplete_base__(
-        current_word,
-        argv[1:])
-
-
-def main(argv):
-    """
-    This is the main function for the Mesos CLI.
-    """
-
-    # Load the CLI config.
-    config = cli.config.Config(settings)
-
-    plugins = cli.util.import_modules(
-        cli.util.join_plugin_paths(settings, config),
-        "plugins")
-
-    cmds = {
-        cli.util.get_module(plugins, plugin).PLUGIN_NAME:
-        cli.util.get_module(plugins, plugin).SHORT_HELP
-        for plugin in plugins.keys()
-    }
-
-    # Parse all incoming arguments using docopt.
-    command_strings = ""
-    if cmds != {}:
-        command_strings = cli.util.format_commands_help(cmds)
-    usage = USAGE.format(commands=command_strings)
-
-    arguments = docopt(usage, argv=argv, version=VERSION, options_first=True)
-
-    cmd = arguments["<command>"]
-    argv = arguments["<args>"]
-
-    # Use the meta-command `__autocomplete__` to perform
-    # autocompletion on the remaining arguments.
-    if cmd == "__autocomplete__":
-        option = "default"
-        comp_words = []
-
-        # If there is an error performing the autocomplete, treat it
-        # as if we were just unable to complete any words. This avoids
-        # passing the erroring stack trace back as the list of words
-        # to complete on.
-        try:
-            option, comp_words = autocomplete(cmds, plugins, config, argv)
-        except Exception:
-            pass
-
-        print option
-        print " ".join(comp_words)
-
-    # Use the meta-command "help" to print help information for the
-    # supplied command and its subcommands.
-    elif cmd == "help":
-        if len(argv) > 0 and argv[0] in cmds:
-            plugin = cli.util.get_module(plugins, argv[0])
-            plugin_class = getattr(plugin, plugin.PLUGIN_CLASS)
-            plugin_class(settings, config).main(argv[1:] + ["--help"])
-        else:
-            main(["--help"])
-
-    # Run the command through its plugin.
-    elif cmd in cmds.keys():
-        plugin = cli.util.get_module(plugins, cmd)
-        plugin_class = getattr(plugin, plugin.PLUGIN_CLASS)
-        plugin_class(settings, config).main(argv)
-
-    # Print help information if no commands match.
-    else:
-        main(["--help"])
-
-
-if __name__ == "__main__":
-    try:
-        main(sys.argv[1:])
-    except CLIException as exception:
-        sys.exit("Error: {error}.".format(error=str(exception)))
-    except KeyboardInterrupt:
-        pass

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/bin/mesos
----------------------------------------------------------------------
diff --git a/src/cli_new/bin/mesos b/src/cli_new/bin/mesos
deleted file mode 100755
index c5152a2..0000000
--- a/src/cli_new/bin/mesos
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/usr/bin/env bash
-
-CURRDIR="$(cd "$(dirname "$0")" && pwd)"
-
-source ${CURRDIR}/../activate
-python ${CURRDIR}/main.py "$@"

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/bin/mesos-cli-tests
----------------------------------------------------------------------
diff --git a/src/cli_new/bin/mesos-cli-tests b/src/cli_new/bin/mesos-cli-tests
deleted file mode 100755
index 07659e0..0000000
--- a/src/cli_new/bin/mesos-cli-tests
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/usr/bin/env bash
-
-CURRDIR="$(cd "$(dirname "$0")" && pwd)"
-
-source ${CURRDIR}/../activate
-python ${CURRDIR}/../tests/main.py "$@"

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/bin/settings.py
----------------------------------------------------------------------
diff --git a/src/cli_new/bin/settings.py b/src/cli_new/bin/settings.py
deleted file mode 100644
index d42df04..0000000
--- a/src/cli_new/bin/settings.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-This file defines the default settings of the mesos-cli. It also takes care
-of updating the default configuration from reading environment variables or
-parsing a configuration file.
-"""
-
-import os
-
-
-# There is no version module included in this package. However,
-# when creating an executable using pyinstaller, a version.py
-# file will be autogenerated and inserted into the PYTHONPATH.
-# When this happens we import it to set the VERSION.
-try:
-    # pylint: disable=F0401,W0611
-    from version import VERSION
-except Exception:
-    VERSION = "Development"
-
-# The top-level directory of this project.
-PROJECT_DIR = os.path.join(os.path.dirname(__file__), os.pardir)
-
-# The builtin plugins.
-PLUGINS = [
-    os.path.join(PROJECT_DIR, "lib", "mesos", "plugins", "config")
-]
-
-DEFAULT_MESOS_CLI_CONFIG = os.path.join(
-    os.path.expanduser("~"),
-    ".mesos",
-    "config.toml")

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/bootstrap
----------------------------------------------------------------------
diff --git a/src/cli_new/bootstrap b/src/cli_new/bootstrap
deleted file mode 100755
index 4193d3f..0000000
--- a/src/cli_new/bootstrap
+++ /dev/null
@@ -1,107 +0,0 @@
-#!/usr/bin/env bash
-
-# This script sets up a Python virtualenv for the Mesos CLI.
-# This creates a new virtualenv, installs the necessary Python
-# dependencies inside the virtualenv, and enables bash auto
-# completion for the Mesos CLI.
-
-set -e
-trap "exit 1" INT
-
-CURRDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-
-: ${VIRTUALENV_NAME:="mesos-cli"}
-: ${VIRTUALENV_DIRECTORY:="${CURRDIR}/.virtualenv"}
-
-: ${PYTHON:="$(which python)"}
-: ${VIRTUALENV:="$(which virtualenv)"}
-
-OLD_PYTHONPATH="${PYTHONPATH}"
-PYTHONPATH=""
-
-# If we already have a virtual environment activated,
-# bail out and advise the user to deactivate.
-OLD_VIRTUAL_ENV="${VIRTUAL_ENV}"
-if [ "${OLD_VIRTUAL_ENV}" != "" ]; then
-  echo "Please deactivate your current virtual environment in order to continue!"
-  echo "source deactivate"
-  exit 1
-fi
-
-# Verify that python and virtualenv are installed.
-if [ "${PYTHON}" = "" ]; then
-  echo "You must have python installed in order to continue..."
-  exit 1
-fi
-
-if [ "${VIRTUALENV}" = "" ]; then
-  # Search for a locally installed virtualenv.
-  # See https://docs.python.org/2/library/site.html#site.USER_SITE for details.
-  VIRTUALENV=$(${PYTHON} -c "import site; print site.USER_SITE")/virtualenv.py
-
-  if [ ! -f "${VIRTUALENV}" ]; then
-    echo "You must have virtualenv installed in order to continue..."
-    exit 1
-  fi
-fi
-
-PYTHON_MAJOR=$(${PYTHON} -c 'import sys; print(sys.version_info[0])')
-PYTHON_MINOR=$(${PYTHON} -c 'import sys; print(sys.version_info[1])')
-
-if [ "${PYTHON_MAJOR}" != "2" ] || [ "${PYTHON_MINOR}" -lt "6" ]; then
-  echo "You must be running python 2.6 or 2.7 in order to continue."
-  echo "Consider running as 'PYTHON=python2 ./bootstrap' or similar."
-  exit 1
-fi
-
-# Set up a virtual environment for the CLI.
-${PYTHON} ${VIRTUALENV} --python=${PYTHON} \
-                        --clear \
-                        --no-site-packages \
-                        --prompt="(${VIRTUALENV_NAME}) " \
-                        ${VIRTUALENV_DIRECTORY} || true
-
-source ${VIRTUALENV_DIRECTORY}/bin/activate
-SITE_PACKAGES=$(python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())")
-echo ${SITE_PACKAGES}
-echo "${CURRDIR}/lib" > ${SITE_PACKAGES}/_virtualenv_path_extensions.pth
-echo "${CURRDIR}/../python/lib" >> ${SITE_PACKAGES}/_virtualenv_path_extensions.pth
-pip install --upgrade pip
-pip install -r ${CURRDIR}/pip-requirements.txt
-deactivate
-
-# Add custom postactivate / predeactivate scripts to add / remove
-# the bin directory of this project to the current path in the
-# virtual environment (as well as setup bash auto completion).
-cat > ${VIRTUALENV_DIRECTORY}/bin/postactivate << EOF
-#!/usr/bin/env bash
-PROJECT_BIN="${CURRDIR}/bin"
-PATH="\${PROJECT_BIN}:\${PATH}"
-PYTHONPATH=""
-
-EOF
-cat ${CURRDIR}/mesos.bash_completion >> ${VIRTUALENV_DIRECTORY}/bin/postactivate
-
-cat > ${VIRTUALENV_DIRECTORY}/bin/predeactivate << EOF
-#!/usr/bin/env bash
-PROJECT_BIN="${CURDRDIR}/bin"
-PATH=\${PATH/":\${PROJECT_BIN}"/}
-PATH=\${PATH/"\${PROJECT_BIN}:"/}
-PYTHONPATH="${OLD_PYTHONPATH}"
-
-complete -r mesos
-EOF
-
-if [ "${VIRTUALENV_DIRECTORY}" = "${CURRDIR}/.virtualenv" ]; then
-  # Print some info about the sucess of the installation.
-  echo ""
-  echo "Setup complete!"
-  echo ""
-  echo "To begin working, simply activate your virtual"
-  echo "environment and deactivate it when you are done."
-  echo ""
-  echo "    $ source activate"
-  echo "    $ mesos <command> [<args>...]"
-  echo "    $ source deactivate"
-  echo ""
-fi

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/deactivate
----------------------------------------------------------------------
diff --git a/src/cli_new/deactivate b/src/cli_new/deactivate
deleted file mode 100644
index 3dbe167..0000000
--- a/src/cli_new/deactivate
+++ /dev/null
@@ -1,4 +0,0 @@
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-
-source ${DIR}/.virtualenv/bin/predeactivate
-deactivate

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/lib/cli/__init__.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/cli/__init__.py b/src/cli_new/lib/cli/__init__.py
deleted file mode 100644
index e594b30..0000000
--- a/src/cli_new/lib/cli/__init__.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-Mesos CLI Module
-"""
-
-from . import config
-from . import exceptions
-from . import plugins
-from . import util

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/lib/cli/config.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/cli/config.py b/src/cli_new/lib/cli/config.py
deleted file mode 100644
index 36a32f9..0000000
--- a/src/cli_new/lib/cli/config.py
+++ /dev/null
@@ -1,64 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-Config class to manage the configuration file.
-"""
-
-import os
-import toml
-
-from cli.exceptions import CLIException
-
-
-class Config(object):
-    """
-    The Config class loads the configuration file on initialization and has
-    one method for each element that can be specified in the config file.
-    """
-
-    def __init__(self, settings):
-        # Load the configuration file path for the CLI.
-        if os.environ.get("MESOS_CLI_CONFIG"):
-            self.path = os.environ["MESOS_CLI_CONFIG"]
-        else:
-            self.path = settings.DEFAULT_MESOS_CLI_CONFIG
-
-        # Load the configuration file as a TOML file.
-        try:
-            self.data = toml.load(self.path)
-        except Exception as exception:
-            raise CLIException("Error loading config file as TOML: {error}"
-                               .format(error=exception))
-
-    def plugins(self):
-        """
-        Parse the plugins listed in the configuration file and return them.
-        """
-        # Allow extra plugins to be pulled in from the configuration file.
-        if "plugins" in self.data:
-            if not isinstance(self.data["plugins"], list):
-                raise CLIException("Unable to parse config file '{path}':"
-                                   " 'plugins' field must be a list"
-                                   .format(path=self.path))
-
-            for plugin in self.data["plugins"]:
-                if not os.path.exists(plugin):
-                    raise CLIException("Plugin path not found: {path}"
-                                       .format(path=plugin))
-            return self.data["plugins"]
-
-        return []

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/lib/cli/docopt.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/cli/docopt.py b/src/cli_new/lib/cli/docopt.py
deleted file mode 100644
index 86a4e9c..0000000
--- a/src/cli_new/lib/cli/docopt.py
+++ /dev/null
@@ -1,90 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-Unfortunately, docopt doesn't support multi-word commands.  This is
-important for supporting things like:
-
-mesos cluster ps <args>...
-
-However, it looks like some plans are in place for supporting it in the
-future: https://github.com/docopt/docopt/issues/41
-
-The proposal is to add a "program" keyword argument to docopt to specify the
-full set of words used to represent the command. Since this is not yet
-supported officially, we include the hack below to make it work for us. We
-essentially intercept the call to docopt and make it work with such a "program"
-argument.
-
-To make it work, we inspect the value of "program" and search and replace all
-instances of it in the usage string with a transformed version of it to make it
-a single word (i.e. we replace all spaces with dashes: echo $program | s/
-/-/g). This essentially turns all multi-word commands in the usage string into
-dash-separated single words (e.g., s/mesos cluster ps/mesos-cluster-ps/g). With
-this in place, we then pass this usage string to the original docopt for
-parsing.
-
-Unfortunately, doing things this way means that docopt (by default) will print
-the usage string containing the dashes. To avoid this, we intercept all paths
-where docopt does the printing itself, and transform the usage string back to
-its original form.
-
-Hopefully we can remove this brutal hack at some point in the future
-once docopt supports the "program" argument natively.
-"""
-
-from __future__ import absolute_import
-import os
-import sys
-
-# pylint: disable=F0401
-from docopt import docopt as real_docopt, DocoptExit
-
-
-def docopt(usage, **keywords):
-    """ A wrapper around the real docopt parser. """
-    new_usage = usage
-
-    if "program" in keywords:
-        program = keywords.pop("program")
-        new_usage = usage.replace(program, program.replace(" ", "-"))
-
-    try:
-        stdout = sys.stdout
-
-        with open(os.devnull, 'w') as nullfile:
-            sys.stdout = nullfile
-            arguments = real_docopt(new_usage, **keywords)
-            sys.stdout = stdout
-
-        return arguments
-
-    except DocoptExit:
-        sys.stdout = stdout
-        print >> sys.stderr, usage.strip()
-        sys.exit(1)
-
-    except SystemExit:
-        sys.stdout = stdout
-
-        if "argv" in keywords and any(h in ("-h", "--help")
-                                      for h in keywords["argv"]):
-            print usage.strip()
-        elif "version" in keywords and any(v in ("--version")
-                                           for v in keywords["argv"]):
-            print keywords["version"].strip()
-
-        sys.exit()

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/lib/cli/exceptions.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/cli/exceptions.py b/src/cli_new/lib/cli/exceptions.py
deleted file mode 100644
index c78f4a9..0000000
--- a/src/cli_new/lib/cli/exceptions.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-CLIException Class
-"""
-
-class CLIException(Exception):
-    """
-    Exceptions class to handle all CLI errors.
-    """
-    pass

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/lib/cli/http.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/cli/http.py b/src/cli_new/lib/cli/http.py
deleted file mode 100644
index 03d6031..0000000
--- a/src/cli_new/lib/cli/http.py
+++ /dev/null
@@ -1,77 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-A collection of http related functions used by the CLI and its Plugins.
-"""
-
-import json
-import urllib2
-import time
-
-from cli.exceptions import CLIException
-
-
-def read_endpoint(addr, endpoint):
-    """
-    Read the specified endpoint and return the results.
-    """
-    try:
-        url = "http://{addr}/{endpoint}".format(addr=addr, endpoint=endpoint)
-
-        http_response = urllib2.urlopen(url).read().decode("utf-8")
-    except Exception as exception:
-        raise CLIException("{error}".format(error=str(exception)))
-
-    return http_response
-
-
-def get_json(addr, endpoint, condition=None, timeout=5):
-    """
-    Return the contents of the 'endpoint' at 'addr' as JSON data
-    subject to the condition specified in 'condition'. If we are
-    unable to read the data or unable to meet the condition within
-    'timeout' seconds we throw an error.
-    """
-    start_time = time.time()
-
-    while True:
-        data = None
-
-        try:
-            data = read_endpoint(addr, endpoint)
-        except Exception as exception:
-            pass
-
-        if data:
-            try:
-                data = json.loads(data)
-            except Exception as exception:
-                raise CLIException("Could not load JSON from '{data}': {error}"
-                                   .format(data=data, error=str(exception)))
-
-            if not condition:
-                return data
-
-            if condition(data):
-                return data
-
-        if time.time() - start_time > timeout:
-            raise CLIException("Failed to get data within {seconds} seconds:"
-                               " {error}"
-                               .format(seconds=str(timeout), error=exception))
-
-        time.sleep(0.1)

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/lib/cli/plugins/__init__.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/cli/plugins/__init__.py b/src/cli_new/lib/cli/plugins/__init__.py
deleted file mode 100644
index e743772..0000000
--- a/src/cli_new/lib/cli/plugins/__init__.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-Plugins Module
-"""
-
-# pylint: disable=W0401
-from .base import *

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/lib/cli/plugins/base.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/cli/plugins/base.py b/src/cli_new/lib/cli/plugins/base.py
deleted file mode 100644
index edbe1ec..0000000
--- a/src/cli_new/lib/cli/plugins/base.py
+++ /dev/null
@@ -1,177 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-Plugin's Base Class
-"""
-
-import sys
-
-import cli
-
-from cli.docopt import docopt
-
-
-PLUGIN_NAME = "base-plugin"
-PLUGIN_CLASS = "PluginBase"
-
-VERSION = "Mesos Plugin Base 1.0"
-
-SHORT_HELP = "This is the base plugin from which all other plugins inherit."
-
-USAGE = \
-"""
-{short_help}
-
-Usage:
-  mesos {plugin} (-h | --help)
-  mesos {plugin} --version
-  mesos {plugin} <command> (-h | --help)
-  mesos {plugin} <command> [<args>...] [options]
-
-Options:
-  -h --help  Show this screen.
-  --version  Show version info.
-
-Commands:
-{commands}
-"""
-
-SUBCOMMAND_USAGE = \
-"""{short_help}
-
-Usage:
-  mesos {plugin} {command} (-h | --help)
-  mesos {plugin} {command} --version
-  mesos {plugin} {command} {arguments} [options]
-
-Options:
-{flags}
-
-Description:
-{long_help}
-"""
-
-
-class PluginBase(object):
-    """
-    Base class from which all CLI plugins should inherit.
-    """
-    # pylint: disable=R0903
-    COMMANDS = {}
-
-    def __setup__(self, command, argv):
-        pass
-
-    def __module_reference__(self):
-        return sys.modules[self.__module__]
-
-    def __init__(self, settings, config):
-        # pylint: disable=C0103
-        self.PLUGIN_NAME = PLUGIN_NAME
-        self.PLUGIN_CLASS = PLUGIN_CLASS
-        self.VERSION = VERSION
-        self.SHORT_HELP = SHORT_HELP
-        self.USAGE = USAGE
-
-        module = self.__module_reference__()
-        if hasattr(module, "PLUGIN_NAME"):
-            self.PLUGIN_NAME = getattr(module, "PLUGIN_NAME")
-        if hasattr(module, "PLUGIN_CLASS"):
-            self.PLUGIN_CLASS = getattr(module, "PLUGIN_CLASS")
-        if hasattr(module, "VERSION"):
-            self.VERSION = getattr(module, "VERSION")
-        if hasattr(module, "SHORT_HELP"):
-            self.SHORT_HELP = getattr(module, "SHORT_HELP")
-        if hasattr(module, "USAGE"):
-            self.USAGE = getattr(module, "USAGE")
-
-        self.settings = settings
-        self.config = config
-
-    def __autocomplete__(self, command, current_word, argv):
-        # pylint: disable=W0612,W0613,R0201
-        return ("default", [])
-
-    def __autocomplete_base__(self, current_word, argv):
-        option = "default"
-
-        # <command>
-        comp_words = list(self.COMMANDS.keys())
-        comp_words = cli.util.completions(comp_words, current_word, argv)
-        if comp_words != None:
-            return (option, comp_words)
-
-        # <args>...
-        # pylint: disable=R0204
-        comp_words = self.__autocomplete__(argv[0], current_word, argv[1:])
-
-        # In general, we expect a tuple to be returned from __autocomplete__,
-        # with the first element being a valid autocomplete option, and the
-        # second being a list of completion words. However, in the common
-        # case we usually use the default option, so it's OK for a plugin to
-        # just return a list. We will add the "default" option for them.
-        if isinstance(comp_words, tuple):
-            option, comp_words = comp_words
-
-        return (option, comp_words)
-
-    def main(self, argv):
-        """
-        Main method takes argument from top level mesos and parses them
-        to call the appropriate method.
-        """
-        command_strings = cli.util.format_commands_help(self.COMMANDS)
-
-        usage = self.USAGE.format(
-            plugin=self.PLUGIN_NAME,
-            short_help=self.SHORT_HELP,
-            commands=command_strings)
-
-        arguments = docopt(
-            usage,
-            argv=argv,
-            version=self.VERSION,
-            program="mesos " + self.PLUGIN_NAME,
-            options_first=True)
-
-        cmd = arguments["<command>"]
-        argv = arguments["<args>"]
-
-        if cmd in self.COMMANDS.keys():
-            if "external" not in self.COMMANDS[cmd]:
-                argument_format, short_help, long_help, flag_format = \
-                    cli.util.format_subcommands_help(self.COMMANDS[cmd])
-
-                usage = SUBCOMMAND_USAGE.format(
-                    plugin=self.PLUGIN_NAME,
-                    command=cmd,
-                    arguments=argument_format,
-                    flags=flag_format,
-                    short_help=short_help,
-                    long_help=long_help)
-
-                arguments = docopt(
-                    usage,
-                    argv=argv,
-                    program="mesos " + self.PLUGIN_NAME + " " + cmd,
-                    version=self.VERSION,
-                    options_first=True)
-
-            self.__setup__(cmd, argv)
-            getattr(self, cmd.replace("-", "_"))(arguments)
-        else:
-            self.main(["--help"])

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/lib/cli/plugins/config/__init__.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/cli/plugins/config/__init__.py b/src/cli_new/lib/cli/plugins/config/__init__.py
deleted file mode 100644
index cf5673d..0000000
--- a/src/cli_new/lib/cli/plugins/config/__init__.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-Config module.
-"""
-
-# pylint: disable=wildcard-import
-from .main import *

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/lib/cli/plugins/config/main.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/cli/plugins/config/main.py b/src/cli_new/lib/cli/plugins/config/main.py
deleted file mode 100644
index 41bdb60..0000000
--- a/src/cli_new/lib/cli/plugins/config/main.py
+++ /dev/null
@@ -1,98 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-The config plugin.
-"""
-
-import os
-import sys
-
-import cli
-
-from cli.exceptions import CLIException
-from cli.plugins import PluginBase
-from cli.util import Table
-
-
-PLUGIN_NAME = "config"
-PLUGIN_CLASS = "Config"
-
-VERSION = "Mesos CLI Config Plugin"
-
-SHORT_HELP = "Interacts with the Mesos CLI configuration file"
-
-
-class Config(PluginBase):
-    """
-    The config plugin.
-    """
-
-    COMMANDS = {
-        "plugins": {
-            "arguments": [],
-            "flags": {},
-            "short_help": "Print the plugins that can be used.",
-            "long_help": "Print the plugins that can be used."
-        },
-        "show": {
-            "arguments": [],
-            "flags": {},
-            "short_help": "Show the contents of the configuration file.",
-            "long_help": "Show the contents of the configuration file."
-        }
-    }
-
-    def plugins(self, argv):
-        """
-        Parse and load the builtin plugins and the ones in the configuration
-        file. If this method is called using 'mesos config plugins', it
-        displays the plugins that can be used.
-        """
-        # pylint: disable=unused-argument
-        plugins_table = Table(["NAME", "DESCRIPTION"])
-
-        # Load the plugins
-        plugins = cli.util.import_modules(
-            cli.util.join_plugin_paths(self.settings, self.config),
-            "plugins")
-
-        for plugin in plugins:
-            plugins_table.add_row([
-                cli.util.get_module(plugins, plugin).PLUGIN_NAME,
-                cli.util.get_module(plugins, plugin).SHORT_HELP
-            ])
-        sys.stdout.write("{}\n".format(plugins_table))
-
-    def show(self, argv):
-        """
-        Show the contents of the configuration file.
-        """
-        # pylint: disable=unused-argument
-        config_file = self.config.path
-        if not os.path.isfile(config_file):
-            raise CLIException("Unable to show the config file,"
-                               " '{path}' does not exist"
-                               .format(path=config_file))
-
-        with open(config_file, 'r') as stream:
-            try:
-                sys.stdout.write("{stream}\n"
-                                 .format(stream=stream.read().rstrip()))
-            except Exception as exception:
-                raise CLIException("Unable to read config file '{path}':"
-                                   " {error}"
-                                   .format(path=config_file, error=exception))

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/lib/cli/tests/__init__.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/cli/tests/__init__.py b/src/cli_new/lib/cli/tests/__init__.py
deleted file mode 100644
index 0daf288..0000000
--- a/src/cli_new/lib/cli/tests/__init__.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-Mesos CLI unit tests module.
-"""
-
-# pylint: disable=W0401
-from .base import *
-from .tests import *

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/lib/cli/tests/base.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/cli/tests/base.py b/src/cli_new/lib/cli/tests/base.py
deleted file mode 100644
index 62a4ee8..0000000
--- a/src/cli_new/lib/cli/tests/base.py
+++ /dev/null
@@ -1,422 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-Set of classes and helper functions for building unit tests for the Mesos CLI.
-"""
-
-import os
-import shutil
-import StringIO
-import subprocess
-import sys
-import tempfile
-import unittest
-
-import parse
-
-import cli.http as http
-
-from cli.tests.constants import DEFAULT_AGENT_IP
-from cli.tests.constants import DEFAULT_AGENT_PORT
-from cli.tests.constants import DEFAULT_MASTER_IP
-from cli.tests.constants import DEFAULT_MASTER_PORT
-
-from cli.exceptions import CLIException
-
-# Timeout used when creating, killing, and getting data from objects that are
-# part of our test infrastructure.
-TIMEOUT = 5
-
-
-class CLITestCase(unittest.TestCase):
-    """
-    Base class for CLI TestCases.
-    """
-
-    @classmethod
-    def setUpClass(cls):
-        print "\n{class_name}".format(class_name=cls.__name__)
-
-    @staticmethod
-    def default_mesos_build_dir():
-        """
-        Returns the default path of the Mesos build directory. Useful when
-        we wish to use some binaries such as mesos-execute.
-        """
-        tests_dir = os.path.dirname(__file__)
-        cli_dir = os.path.dirname(tests_dir)
-        lib_dir = os.path.dirname(cli_dir)
-        cli_new_dir = os.path.dirname(lib_dir)
-        src_dir = os.path.dirname(cli_new_dir)
-        mesos_dir = os.path.dirname(src_dir)
-        build_dir = os.path.join(mesos_dir, "build")
-
-        if os.path.isdir(build_dir):
-            return build_dir
-        else:
-            raise CLIException("The Mesos build directory"
-                               " does not exist: {path}"
-                               .format(path=build_dir))
-
-# This value is set to the correct path when running tests/main.py. We
-# set it here to make sure that CLITestCase has a MESOS_BUILD_DIR member.
-CLITestCase.MESOS_BUILD_DIR = ""
-
-
-class Executable(object):
-    """
-    This class defines the base class for launching an executable for
-    the CLI unit tests. It will be subclassed by (at least) a
-    'Master', 'Agent', and 'Task' subclass.
-    """
-    def __init__(self):
-        self.name = ""
-        self.executable = ""
-        self.flags = {}
-        self.proc = None
-
-    def __del__(self):
-        if hasattr(self, "proc"):
-            self.kill()
-
-    def launch(self):
-        """
-        Launch 'self.executable'. We assume it is in the system PATH.
-        """
-        if self.proc is not None:
-            raise CLIException("{name} already launched"
-                               .format(name=self.name.capitalize()))
-
-        try:
-            flags = ["--{key}={value}".format(key=key, value=value)
-                     for key, value in self.flags.iteritems()]
-
-            proc = subprocess.Popen(
-                [self.executable] + flags,
-                stdin=subprocess.PIPE,
-                stdout=subprocess.PIPE,
-                stderr=subprocess.STDOUT)
-        except Exception as exception:
-            raise CLIException("Failed to launch '{executable}': {error}"
-                               .format(executable=self.executable,
-                                       error=exception))
-
-        if proc.poll():
-            raise CLIException("Failed to launch '{executable}': {error}"
-                               .format(executable=self.executable,
-                                       error=proc.stdout.read()))
-
-        self.proc = proc
-
-    def kill(self):
-        """
-        Kills a previously launched executable.
-        """
-        if self.proc is None:
-            return
-
-        try:
-            self.proc.kill()
-            self.proc.wait()
-            self.proc = None
-        except Exception as exception:
-            raise CLIException("Could not kill {name}: {error}"
-                               .format(name=self.name, error=exception))
-
-
-class Master(Executable):
-    """
-    This class defines the functions necessary to launch a master in
-    the CLI unit tests.
-    """
-    count = 0
-
-    def __init__(self, flags=None):
-        super(Master, self).__init__()
-
-        if Master.count > 0:
-            raise CLIException("Creating more than one master"
-                               " is currently not possible")
-
-        Master.count += 1
-
-        if flags is None:
-            flags = {}
-
-        if "ip" not in flags:
-            flags["ip"] = DEFAULT_MASTER_IP
-        if "port" not in flags:
-            flags["port"] = DEFAULT_MASTER_PORT
-        if "work_dir" not in flags:
-            flags["work_dir"] = tempfile.mkdtemp()
-
-        self.flags = flags
-        self.name = "master"
-        self.addr = "{ip}:{port}".format(ip=flags["ip"], port=flags["port"])
-        self.executable = os.path.join(
-            CLITestCase.MESOS_BUILD_DIR,
-            "bin",
-            "mesos-{name}.sh".format(name=self.name))
-
-    def __del__(self):
-        super(Master, self).__del__()
-
-        if hasattr(self, "flags"):
-            shutil.rmtree(self.flags["work_dir"])
-
-        Master.count -= 1
-
-
-class Agent(Executable):
-    """
-    This class defines the functions necessary to launch an agent in
-    the CLI unit tests.
-    """
-    count = 0
-
-    def __init__(self, flags=None):
-        super(Agent, self).__init__()
-
-        if Agent.count > 0:
-            raise CLIException("Creating more than one agent"
-                               " is currently not possible")
-
-        Agent.count += 1
-
-        if flags is None:
-            flags = {}
-
-        if "ip" not in flags:
-            flags["ip"] = DEFAULT_AGENT_IP
-        if "port" not in flags:
-            flags["port"] = DEFAULT_AGENT_PORT
-        if "master" not in flags:
-            flags["master"] = "{ip}:{port}".format(
-                ip=DEFAULT_MASTER_IP,
-                port=DEFAULT_MASTER_PORT)
-        if "work_dir" not in flags:
-            flags["work_dir"] = tempfile.mkdtemp()
-        if "runtime_dir" not in flags:
-            flags["runtime_dir"] = tempfile.mkdtemp()
-        # Disabling systemd support on Linux to run without sudo.
-        if "linux" in sys.platform and "systemd_enable_support" not in flags:
-            flags["systemd_enable_support"] = "false"
-
-        self.flags = flags
-        self.name = "agent"
-        self.addr = "{ip}:{port}".format(ip=flags["ip"], port=flags["port"])
-        self.executable = os.path.join(
-            CLITestCase.MESOS_BUILD_DIR,
-            "bin",
-            "mesos-{name}.sh".format(name=self.name))
-
-    def __del__(self):
-        super(Agent, self).__del__()
-
-        if hasattr(self, "flags"):
-            shutil.rmtree(self.flags["work_dir"])
-            shutil.rmtree(self.flags["runtime_dir"])
-
-        Agent.count -= 1
-
-    # pylint: disable=arguments-differ
-    def launch(self, timeout=TIMEOUT):
-        """
-        After starting the agent, we need to make sure it has
-        successfully registered with the master before proceeding.
-        """
-        super(Agent, self).launch()
-
-        try:
-            # pylint: disable=missing-docstring
-            def single_slave(data):
-                return len(data["slaves"]) == 1
-
-            http.get_json(self.flags["master"], "slaves", single_slave, timeout)
-        except Exception as exception:
-            stdout = ""
-            if self.proc.poll():
-                stdout = "\n{output}".format(output=self.proc.stdout.read())
-                self.proc = None
-
-            raise CLIException("Could not get '/slaves' endpoint as JSON with"
-                               " only 1 agent in it: {error}{stdout}"
-                               .format(error=exception, stdout=stdout))
-
-    # pylint: disable=arguments-differ
-    def kill(self, timeout=TIMEOUT):
-        """
-        After killing the agent, we need to make sure it has
-        successfully unregistered from the master before proceeding.
-        """
-        super(Agent, self).kill()
-
-        if self.proc is None:
-            return
-
-        try:
-            # pylint: disable=missing-docstring
-            def no_slaves(data):
-                return len(data["slaves"]) == 0
-
-            http.get_json(self.flags["master"], "slaves", no_slaves, timeout)
-        except Exception as exception:
-            raise CLIException("Could not get '/slaves' endpoint as"
-                               " JSON with 0 agents in it: {error}"
-                               .format(error=exception))
-
-
-class Task(Executable):
-    """
-    This class defines the functions necessary to launch a task in
-    the CLI unit tests.
-    """
-    count = 0
-
-    def __init__(self, flags=None):
-        super(Task, self).__init__()
-
-        if flags is None:
-            flags = {}
-
-        if "master" not in flags:
-            flags["master"] = "{ip}:{port}".format(
-                ip=DEFAULT_MASTER_IP,
-                port=DEFAULT_MASTER_PORT)
-        if "name" not in flags:
-            flags["name"] = "task-{id}".format(id=Task.count)
-            Task.count += 1
-        if "command" not in flags:
-            raise CLIException("No command supplied when creating task")
-
-        self.flags = flags
-        self.name = "task"
-        self.executable = os.path.join(
-            CLITestCase.MESOS_BUILD_DIR,
-            "src",
-            "mesos-execute")
-
-    def __wait_for_containers(self, condition, timeout=TIMEOUT):
-        """
-        Wait for the agent's '/containers' endpoint
-        to return data subject to 'condition'.
-        """
-        try:
-            data = http.get_json(self.flags["master"], "slaves")
-        except Exception as exception:
-            raise CLIException("Could not get '/slaves' endpoint"
-                               " as JSON: {error}"
-                               .format(error=exception))
-
-        if len(data["slaves"]) != 1:
-            raise CLIException("More than one agent detected when"
-                               " reading from '/slaves' endpoint")
-
-        try:
-            agent = parse.parse(
-                "slave({id})@{addr}",
-                data["slaves"][0]["pid"])
-        except Exception as exception:
-            raise CLIException("Unable to parse agent info: {error}"
-                               .format(error=exception))
-
-        try:
-            data = http.get_json(
-                agent["addr"],
-                "containers",
-                condition,
-                timeout)
-        except Exception as exception:
-            raise CLIException("Could not get '/containers' endpoint as"
-                               " JSON subject to condition: {error}"
-                               .format(error=exception))
-
-    # pylint: disable=arguments-differ
-    def launch(self, timeout=TIMEOUT):
-        """
-        After starting the task, we need to make sure its container
-        has actually been added to the agent before proceeding.
-        """
-        super(Task, self).launch()
-
-        try:
-            # pylint: disable=missing-docstring
-            def container_exists(data):
-                return any(container["executor_id"] == self.flags["name"]
-                           for container in data)
-
-            self.__wait_for_containers(container_exists, timeout)
-        except Exception as exception:
-            stdout = ""
-            if self.proc.poll():
-                stdout = "\n{output}".format(output=self.proc.stdout.read())
-                self.proc = None
-
-            raise CLIException("Waiting for container '{name}'"
-                               " failed: {error}{stdout}"
-                               .format(name=self.flags["name"],
-                                       error=exception,
-                                       stdout=stdout))
-
-    # pylint: disable=arguments-differ
-    def kill(self, timeout=TIMEOUT):
-        """
-        After killing the task, we need to make sure its container has
-        actually been removed from the agent before proceeding.
-        """
-        super(Task, self).kill()
-
-        if self.proc is None:
-            return
-
-        try:
-            # pylint: disable=missing-docstring
-            def container_does_not_exist(data):
-                return not any(container["executor_id"] == self.flags["name"]
-                               for container in data)
-
-            self.__wait_for_containers(container_does_not_exist, timeout)
-        except Exception as exception:
-            raise CLIException("Container with name '{name}' still"
-                               " exists after timeout: {error}"
-                               .format(name=self.flags["name"],
-                                       error=exception))
-
-
-def capture_output(command, argv, extra_args=None):
-    """
-    Redirect the output of a command to a string and return it.
-    """
-    if not extra_args:
-        extra_args = {}
-
-    stdout = sys.stdout
-    sys.stdout = StringIO.StringIO()
-
-    try:
-        command(argv, **extra_args)
-    except Exception as exception:
-        # Fix stdout in case something goes wrong
-        sys.stdout = stdout
-        raise CLIException("Could not get command output: {error}"
-                           .format(error=exception))
-
-    sys.stdout.seek(0)
-    output = sys.stdout.read().strip()
-    sys.stdout = stdout
-
-    return output

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/lib/cli/tests/constants.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/cli/tests/constants.py b/src/cli_new/lib/cli/tests/constants.py
deleted file mode 100644
index 5d45d94..0000000
--- a/src/cli_new/lib/cli/tests/constants.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-A collection of constants useful for the CLI unit tests.
-"""
-
-DEFAULT_MASTER_IP = "127.0.0.1"
-DEFAULT_MASTER_PORT = "9090"
-
-DEFAULT_AGENT_IP = "127.0.0.1"
-DEFAULT_AGENT_PORT = "9091"

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/lib/cli/tests/tests.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/cli/tests/tests.py b/src/cli_new/lib/cli/tests/tests.py
deleted file mode 100644
index 79e1036..0000000
--- a/src/cli_new/lib/cli/tests/tests.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-Tests that test the test infrastructure itself.
-"""
-
-from cli.tests import capture_output
-from cli.tests import CLITestCase
-from cli.tests import Agent
-from cli.tests import Master
-from cli.tests import Task
-
-
-class TestInfrastructure(CLITestCase):
-    """
-    This class tests the functionality of the test
-    infrastructure used to run all other CLI tests.
-    """
-    def test_launch_binaries(self):
-        """
-        Tests the launching and killing of
-        a mesos master, agent, and task.
-        """
-        master = Master()
-        master.launch()
-
-        agent = Agent()
-        agent.launch()
-
-        task = Task({"command": "sleep 1000"})
-        task.launch()
-
-        task.kill()
-        agent.kill()
-        master.kill()
-
-    def test_capture_output(self):
-        """
-        Tests the ability to capture the output
-        from an arbitrary CLI sub-command.
-        """
-        template = "Arguments: {args}"
-        arguments = ["argument1", "argument2"]
-
-        # pylint: disable=missing-docstring
-        def command(args):
-            print template.format(args=args)
-
-        output = capture_output(command, arguments)
-
-        self.assertEqual(output, template.format(args=arguments))

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/lib/cli/util.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/cli/util.py b/src/cli_new/lib/cli/util.py
deleted file mode 100644
index 7371f83..0000000
--- a/src/cli_new/lib/cli/util.py
+++ /dev/null
@@ -1,259 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-A collection of helper functions used by the CLI and its Plugins.
-"""
-
-import imp
-import importlib
-import os
-import re
-import textwrap
-
-from cli.exceptions import CLIException
-
-
-def import_modules(package_paths, module_type):
-    """
-    Looks for python packages under `package_paths` and imports
-    them as modules. Returns a dictionary of the basename of the
-    `package_paths` to the imported modules.
-    """
-    modules = {}
-    for package_path in package_paths:
-        # We put the imported module into the namespace of
-        # "mesos.<module_type>.<>" to keep it from cluttering up
-        # the import namespace elsewhere.
-        package_name = os.path.basename(package_path)
-        package_dir = os.path.dirname(package_path)
-        module_name = "cli." + module_type + "." + package_name
-        try:
-            module = importlib.import_module(module_name)
-        except Exception:
-            obj, filename, data = imp.find_module(package_name, [package_dir])
-            module = imp.load_module(module_name, obj, filename, data)
-        modules[package_name] = module
-
-    return modules
-
-
-def get_module(modules, import_path):
-    """
-    Given a modules dictionary returned by `import_modules()`,
-    return a reference to the module at `import_path` relative
-    to the base module. For example, get_module(modules, "example.stuff")
-    will return a reference to the "stuff" module inside the
-    imported "example" plugin.
-    """
-    import_path = import_path.split('.')
-    try:
-        module = modules[import_path[0]]
-        if len(import_path) > 1:
-            module = getattr(module, ".".join(import_path[1:]))
-    except Exception as exception:
-        raise CLIException("Unable to get module: {error}"
-                           .format(error=str(exception)))
-
-    return module
-
-
-def completions(comp_words, current_word, argv):
-    """
-    Helps autocomplete by returning the appropriate
-    completion words under three conditions.
-
-    1) Returns `comp_words` if the completion word is
-       potentially in that list.
-    2) Returns an empty list if there is no possible
-       completion.
-    3) Returns `None` if the autocomplete is already done.
-    """
-    comp_words += ["-h", "--help", "--version"]
-
-    if len(argv) == 0:
-        return comp_words
-
-    if len(argv) == 1:
-        if argv[0] not in comp_words and current_word:
-            return comp_words
-
-        if argv[0] in comp_words and current_word:
-            return comp_words
-
-        if argv[0] not in comp_words and not current_word:
-            return []
-
-        if argv[0] in comp_words and not current_word:
-            return None
-
-    if len(argv) > 1 and argv[0] not in comp_words:
-        return []
-
-    if len(argv) > 1 and argv[0] in comp_words:
-        return None
-
-    raise CLIException("Unreachable")
-
-
-def format_commands_help(cmds):
-    """
-    Helps format plugin commands for display.
-    """
-    longest_cmd_name = max(cmds.keys(), key=len)
-
-    help_string = ""
-    for cmd in sorted(cmds.keys()):
-        # For the top-level entry point, `cmds` is a single-level
-        # dictionary with `short_help` as the values. For plugins,
-        # `cmds` is a two-level dictionary, where `short_help` is a
-        # field in each sub-dictionary.
-        short_help = cmds[cmd]
-        if isinstance(short_help, dict):
-            short_help = short_help["short_help"]
-
-        num_spaces = len(longest_cmd_name) - len(cmd) + 2
-        help_string += "  %s%s%s\n" % (cmd, " " * num_spaces, short_help)
-
-    return help_string
-
-
-def format_subcommands_help(cmd):
-    """
-    Helps format plugin subcommands for display.
-    """
-    arguments = " ".join(cmd["arguments"])
-    short_help = cmd["short_help"]
-    long_help = textwrap.dedent(cmd["long_help"].rstrip())
-    long_help = "  " + "\n  ".join(long_help.split('\n'))
-    flags = cmd["flags"]
-    flags["-h --help"] = "Show this screen."
-    flag_string = ""
-
-    if len(flags.keys()) != 0:
-        longest_flag_name = max(flags.keys(), key=len)
-        for flag in sorted(flags.keys()):
-            num_spaces = len(longest_flag_name) - len(flag) + 2
-            flag_string += "  %s%s%s\n" % (flag, " " * num_spaces, flags[flag])
-
-    return (arguments, short_help, long_help, flag_string)
-
-
-def join_plugin_paths(settings, config):
-    """
-    Return all the plugin paths combined
-    from both settings and the config file.
-    """
-    builtin_paths = settings.PLUGINS
-
-    try:
-        config_paths = config.plugins()
-    except Exception as exception:
-        raise CLIException("Error: {error}.".format(error=str(exception)))
-
-    return builtin_paths + config_paths
-
-
-class Table(object):
-    """
-    Defines a custom table structure for printing to the terminal.
-    """
-    def __init__(self, columns):
-        """
-        Initialize a table with a list of column names
-        to act as headers for each column in the table.
-        """
-        if not isinstance(columns, list):
-            raise CLIException("Column headers must be supplied as a list")
-
-        for column in columns:
-            if re.search(r"(\s)\1{2,}", column):
-                raise CLIException("Column headers cannot have more"
-                                   " than one space between words")
-
-        self.table = [columns]
-        self.padding = [len(column) for column in columns]
-
-    def __getitem__(self, index):
-        return list(self.table[index])
-
-    def dimensions(self):
-        """
-        Returns the dimensions of the table as (<num-rows>, <num-columns>).
-        """
-        return (len(self.table), len(self.table[0]))
-
-    def add_row(self, row):
-        """
-        Add a row to the table. Input must be a list where each entry
-        corresponds to its respective column in order.
-        """
-        if len(row) != len(self.table[0]):
-            raise CLIException("Number of entries and columns do not match!")
-
-        # Adjust padding for each column.
-        for index, elem in enumerate(row):
-            if len(elem) > self.padding[index]:
-                self.padding[index] = len(elem)
-
-        self.table.append(row)
-
-    def __str__(self):
-        """
-        Convert a table to string for printing.
-        """
-        table_string = ""
-        for r_index, row in enumerate(self.table):
-            for index, entry in enumerate(row):
-                table_string += "%s%s" % \
-                        (entry, " " * (self.padding[index] - len(entry) + 2))
-
-            if r_index != len(self.table) - 1:
-                table_string += "\n"
-
-        return table_string
-
-    @staticmethod
-    def parse(string):
-        """
-        Parse a string previously printed as a `Table` back into a `Table`.
-        """
-        lines = string.split("\n")
-
-        # Find the location and contents of column headers in the string.
-        # Assume only single spaces between words in column headers.
-        matches = re.finditer(r"([\w\d]+\s?[\w\d]+)+", lines[0])
-        columns = [(m.start(), m.group()) for m in matches]
-
-        # Build a table from the column header contents.
-        table = Table([c[1] for c in columns])
-
-        # Fill in the subsequent rows.
-        for line in lines[1:]:
-            row = []
-            start_indices = [c[0] for c in columns]
-
-            for i, start_index in enumerate(start_indices):
-                if i + 1 < len(start_indices):
-                    column = line[start_index:start_indices[i + 1]]
-                else:
-                    column = line[start_index:]
-
-                row.append(str(column.strip()))
-
-            table.add_row(row)
-
-        return table

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/mesos.bash_completion
----------------------------------------------------------------------
diff --git a/src/cli_new/mesos.bash_completion b/src/cli_new/mesos.bash_completion
deleted file mode 100644
index 2121181..0000000
--- a/src/cli_new/mesos.bash_completion
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/usr/bin/env bash
-
-# This bash completion script works by invoking the mesos command itself with a
-# "magic" subcommand called "__autocomplete__" and then forwarding all of the
-# arguments to it. The mesos command takes care of parsing the arguments and
-# returning the list of valid completions for the current word.
-_mesos() {
-    local cur cmd args rets
-    local option words
-    local OIFS
-
-    cur="${COMP_WORDS[${COMP_CWORD}]}"
-    cmd="${COMP_WORDS[0]}"
-    args=(${COMP_WORDS[@]:1})
-
-    # The __autocomplete__ command will return two lines of text (the first
-    # being the completion mode (default, nospace, etc.) and the second being a
-    # space-separated list of completion words). To handle this, we temporarily
-    # change the shell separator to '\n' instead of ' ' in order to interpret
-    # the results as exactly two values.
-    OIFS=${IFS}
-    IFS=$'\n'
-    rets=($(${cmd} __autocomplete__ "${cur}" ${args[*]}))
-    IFS=${OIFS}
-
-    option="${rets[0]}"
-    words="${rets[1]}"
-
-    # Reset the completion mode to be whatever value was returned by
-    # the __autocomplete__ command.
-    complete -o ${option} -F _mesos mesos
-
-    # Build the array of completion words.
-    COMPREPLY=( $(compgen -W "${words}" -- ${cur}) )
-
-    # If there are no completion words, then reset the completion to "nospace"
-    # mode so that hitting tab will not produce a space after the current word.
-    # This step is necessary since the mode might have been changed above.
-    if [ "${#COMPREPLY[@]}" = "0" ]; then
-        complete -o nospace -F _mesos mesos
-        COMPREPLY=()
-    fi
-
-    return 0
-}
-complete -F _mesos mesos

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/pip-requirements.txt
----------------------------------------------------------------------
diff --git a/src/cli_new/pip-requirements.txt b/src/cli_new/pip-requirements.txt
deleted file mode 100644
index 7aeac34..0000000
--- a/src/cli_new/pip-requirements.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-astroid==1.4.8
-backports.functools-lru-cache==1.2.1
-configparser==3.5.0
-docopt==0.6.2
-isort==4.2.5
-lazy-object-proxy==1.2.2
-mccabe==0.5.2
-parse==1.8.0
-Pygments==2.1.3
-PyInstaller==3.1.1
-pylint==1.6.4
-six==1.10.0
-termcolor==1.1.0
-toml==0.9.2
-tox==2.7.0
-wrapt==1.10.8

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/pylint.config
----------------------------------------------------------------------
diff --git a/src/cli_new/pylint.config b/src/cli_new/pylint.config
deleted file mode 100644
index 63fbb94..0000000
--- a/src/cli_new/pylint.config
+++ /dev/null
@@ -1,26 +0,0 @@
-[MASTER]
-ignore=.git
-
-[MESSAGES CONTROL]
-disable=I0011,no-self-use,fixme
-
-[REPORTS]
-reports=no
-
-[BASIC]
-bad-functions=input,file
-good-names=i,j,k,f,ip,_
-min-public-methods=0
-
-[FORMAT]
-max-line-length=80
-indent-string='    '
-
-[DESIGN]
-max-returns=100
-
-[EXCEPTIONS]
-overgeneral-exceptions=
-
-[TYPECHECK]
-ignored-modules = netifaces

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/cli_new/tests/main.py
----------------------------------------------------------------------
diff --git a/src/cli_new/tests/main.py b/src/cli_new/tests/main.py
deleted file mode 100644
index 3e4d2e4..0000000
--- a/src/cli_new/tests/main.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-This is the main executable of the mesos-cli unit tests.
-"""
-
-import unittest
-
-from termcolor import colored
-
-from cli.tests import CLITestCase
-
-# pylint: disable=unused-import
-# We import the tests that we want to run.
-from cli.tests import TestInfrastructure
-
-if __name__ == '__main__':
-    CLITestCase.MESOS_BUILD_DIR = CLITestCase.default_mesos_build_dir()
-
-    print colored("Running the Mesos CLI unit tests", "yellow")
-    unittest.main(verbosity=2, testRunner=unittest.TextTestRunner)

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/python/cli_new/README.md
----------------------------------------------------------------------
diff --git a/src/python/cli_new/README.md b/src/python/cli_new/README.md
new file mode 100644
index 0000000..c5475c7
--- /dev/null
+++ b/src/python/cli_new/README.md
@@ -0,0 +1,83 @@
+# Mesos CLI
+
+## Prerequisites
+
+Make sure you have the following prerequisites
+installed on your system before you begin.
+
+```
+python 2.6 or 2.7
+virtualenv
+```
+
+## Getting Started
+
+Once you you have the prerequisites installed, simply
+run the `bootstrap` script from this directory to set
+up a python virtual environment and start running the tool.
+
+```
+$ ./bootstrap
+
+...
+
+Setup complete!
+
+To begin working, simply activate your virtual environment,
+run the CLI, and then deactivate the virtual environment
+when you are done.
+
+    $ source activate
+    $ mesos <command> [<args>...]
+    $ source deactivate
+```
+
+**NOTE:** The virtual environment will also setup bash
+autocomplete for all `mesos` commands.
+
+
+## Running tests
+
+To run the unit tests developed for the Mesos CLI, use
+`mesos-cli-tests`:
+
+```
+$ ./bootstrap
+
+...
+
+Setup complete!
+
+To begin working, simply activate your virtual environment,
+run the CLI, and then deactivate the virtual environment
+when you are done.
+
+    $ source activate
+    $ mesos-cli-tests
+
+Running the Mesos CLI unit tests
+
+...
+
+OK
+```
+
+
+## Setting up your configuration
+
+In order to use this tool, you will need to create a
+configuration file in your home directory under
+`~/.mesos/config.toml`. A template for this config can be
+seen below:
+
+```
+# The `plugins` is an array listing the absolute paths of the
+# plugins you want to add to the CLI.
+plugins = [
+  "</absolute/path/to/plugin-1/directory>",
+  "</absolute/path/to/plugin-2/directory>"
+]
+```
+
+You can override the location of this configuration file using
+the environment variable `MESOS_CLI_CONFIG`.

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/python/cli_new/activate
----------------------------------------------------------------------
diff --git a/src/python/cli_new/activate b/src/python/cli_new/activate
new file mode 100644
index 0000000..65df76f
--- /dev/null
+++ b/src/python/cli_new/activate
@@ -0,0 +1,4 @@
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
+source ${DIR}/.virtualenv/bin/activate
+source ${DIR}/.virtualenv/bin/postactivate

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/python/cli_new/bin/main.py
----------------------------------------------------------------------
diff --git a/src/python/cli_new/bin/main.py b/src/python/cli_new/bin/main.py
new file mode 100644
index 0000000..5313038
--- /dev/null
+++ b/src/python/cli_new/bin/main.py
@@ -0,0 +1,155 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+This is the main executable of the mesos-cli.
+"""
+
+import sys
+
+import settings
+
+import cli
+
+from cli.docopt import docopt
+from cli.exceptions import CLIException
+
+
+VERSION = "Mesos " + settings.VERSION + " CLI"
+
+SHORT_HELP = "Perform operations on a running Mesos cluster."
+
+USAGE = \
+"""Mesos CLI
+
+Usage:
+  mesos (-h | --help)
+  mesos --version
+  mesos <command> [<args>...]
+
+Options:
+  -h --help  Show this screen.
+  --version  Show version info.
+
+Commands:
+{commands}
+See 'mesos help <command>' for more information on a specific command.
+"""
+
+
+def autocomplete(cmds, plugins, config, argv):
+    """
+    Perform autocomplete for the given input arguments. If not
+    completing a top level command (or "help"), this function passes
+    the arguments down to the appropriate plugins for per-plugin
+    autocompletion.
+    """
+
+    option = "default"
+    current_word = argv[0]
+    argv = argv[1:]
+
+    if len(argv) > 0 and argv[0] == "help":
+        argv = argv[1:]
+
+    comp_words = list(cmds.keys()) + ["help"]
+    comp_words = cli.util.completions(comp_words, current_word, argv)
+    if comp_words != None:
+        return (option, comp_words)
+
+    plugin = cli.util.get_module(plugins, argv[0])
+    plugin_class = getattr(plugin, plugin.PLUGIN_CLASS)
+
+    return plugin_class(settings, config).__autocomplete_base__(
+        current_word,
+        argv[1:])
+
+
+def main(argv):
+    """
+    This is the main function for the Mesos CLI.
+    """
+
+    # Load the CLI config.
+    config = cli.config.Config(settings)
+
+    plugins = cli.util.import_modules(
+        cli.util.join_plugin_paths(settings, config),
+        "plugins")
+
+    cmds = {
+        cli.util.get_module(plugins, plugin).PLUGIN_NAME:
+        cli.util.get_module(plugins, plugin).SHORT_HELP
+        for plugin in plugins.keys()
+    }
+
+    # Parse all incoming arguments using docopt.
+    command_strings = ""
+    if cmds != {}:
+        command_strings = cli.util.format_commands_help(cmds)
+    usage = USAGE.format(commands=command_strings)
+
+    arguments = docopt(usage, argv=argv, version=VERSION, options_first=True)
+
+    cmd = arguments["<command>"]
+    argv = arguments["<args>"]
+
+    # Use the meta-command `__autocomplete__` to perform
+    # autocompletion on the remaining arguments.
+    if cmd == "__autocomplete__":
+        option = "default"
+        comp_words = []
+
+        # If there is an error performing the autocomplete, treat it
+        # as if we were just unable to complete any words. This avoids
+        # passing the erroring stack trace back as the list of words
+        # to complete on.
+        try:
+            option, comp_words = autocomplete(cmds, plugins, config, argv)
+        except Exception:
+            pass
+
+        print option
+        print " ".join(comp_words)
+
+    # Use the meta-command "help" to print help information for the
+    # supplied command and its subcommands.
+    elif cmd == "help":
+        if len(argv) > 0 and argv[0] in cmds:
+            plugin = cli.util.get_module(plugins, argv[0])
+            plugin_class = getattr(plugin, plugin.PLUGIN_CLASS)
+            plugin_class(settings, config).main(argv[1:] + ["--help"])
+        else:
+            main(["--help"])
+
+    # Run the command through its plugin.
+    elif cmd in cmds.keys():
+        plugin = cli.util.get_module(plugins, cmd)
+        plugin_class = getattr(plugin, plugin.PLUGIN_CLASS)
+        plugin_class(settings, config).main(argv)
+
+    # Print help information if no commands match.
+    else:
+        main(["--help"])
+
+
+if __name__ == "__main__":
+    try:
+        main(sys.argv[1:])
+    except CLIException as exception:
+        sys.exit("Error: {error}.".format(error=str(exception)))
+    except KeyboardInterrupt:
+        pass

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/python/cli_new/bin/mesos
----------------------------------------------------------------------
diff --git a/src/python/cli_new/bin/mesos b/src/python/cli_new/bin/mesos
new file mode 100755
index 0000000..c5152a2
--- /dev/null
+++ b/src/python/cli_new/bin/mesos
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+CURRDIR="$(cd "$(dirname "$0")" && pwd)"
+
+source ${CURRDIR}/../activate
+python ${CURRDIR}/main.py "$@"

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/python/cli_new/bin/mesos-cli-tests
----------------------------------------------------------------------
diff --git a/src/python/cli_new/bin/mesos-cli-tests b/src/python/cli_new/bin/mesos-cli-tests
new file mode 100755
index 0000000..07659e0
--- /dev/null
+++ b/src/python/cli_new/bin/mesos-cli-tests
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+CURRDIR="$(cd "$(dirname "$0")" && pwd)"
+
+source ${CURRDIR}/../activate
+python ${CURRDIR}/../tests/main.py "$@"

http://git-wip-us.apache.org/repos/asf/mesos/blob/09fa758b/src/python/cli_new/bin/settings.py
----------------------------------------------------------------------
diff --git a/src/python/cli_new/bin/settings.py b/src/python/cli_new/bin/settings.py
new file mode 100644
index 0000000..d42df04
--- /dev/null
+++ b/src/python/cli_new/bin/settings.py
@@ -0,0 +1,47 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+This file defines the default settings of the mesos-cli. It also takes care
+of updating the default configuration from reading environment variables or
+parsing a configuration file.
+"""
+
+import os
+
+
+# There is no version module included in this package. However,
+# when creating an executable using pyinstaller, a version.py
+# file will be autogenerated and inserted into the PYTHONPATH.
+# When this happens we import it to set the VERSION.
+try:
+    # pylint: disable=F0401,W0611
+    from version import VERSION
+except Exception:
+    VERSION = "Development"
+
+# The top-level directory of this project.
+PROJECT_DIR = os.path.join(os.path.dirname(__file__), os.pardir)
+
+# The builtin plugins.
+PLUGINS = [
+    os.path.join(PROJECT_DIR, "lib", "mesos", "plugins", "config")
+]
+
+DEFAULT_MESOS_CLI_CONFIG = os.path.join(
+    os.path.expanduser("~"),
+    ".mesos",
+    "config.toml")