<NME> cli.py
<BEF> import argparse
import json
import logging
import os
import sys

import coloredlogs
import coloredlogs
from passlib.hash import sha512_crypt

import dcos_installer.async_server
import dcos_installer.config
import dcos_installer.constants
import gen.calc
from dcos_installer.prettyprint import print_header

log = logging.getLogger(__name__)


def setup_logger(options):
    level = 'INFO'
    if options.verbose:
        level = 'DEBUG'
    coloredlogs.install(
        level=level,
        level_styles={
            'warn': {
                'color': 'yellow'
            },
            'error': {
                'color': 'red',
                'bold': True,
            },
        },
        fmt='%(message)s',
        isatty=True
    )
    log.debug("Logger set to DEBUG")


def do_version(args):
    print(json.dumps(
        {
            'version': gen.calc.entry['must']['dcos_version'],
            'variant': os.environ['BOOTSTRAP_VARIANT']},
        indent=2, sort_keys=True))
    return 0


def web_installer(options):
    log.error('The DC/OS web installer (--web) has been removed.\n'
              'Please refer to the DC/OS Installation guide at https://docs.mesosphere.com/1.12/installing/')
    sys.exit(1)


dispatch_dict_simple = {
    'version': (do_version, None, 'Print the DC/OS version'),
    'web': (
        web_installer,
        'Starting DC/OS installer in web mode',
        'Run the web interface'),
    'genconf': (
        lambda args: backend.do_configure(),
        'EXECUTING CONFIGURATION GENERATION',
        'Create DC/OS install files customized according to {}.'.format(dcos_installer.constants.CONFIG_PATH)),
    'aws-cloudformation': (
        lambda args: backend.do_aws_cf_configure(),
        'EXECUTING AWS CLOUD FORMATION TEMPLATE GENERATION',
        'Generate AWS Advanced AWS CloudFormation templates using the provided config')
}


# TODO(cmaloney): This should only be in enterprise / isn't useful in open currently.
def do_hash_password(password):
    if password is None:
        password = ''
        while True:
            password = input('Password: ')
            if password:
                break
            else:
                log.error('Must provide a non-empty password')

    print_header("HASHING PASSWORD TO SHA512")
    hashed_password = sha512_crypt.encrypt(password)
    return hashed_password


def dispatch(args):
    """ Dispatches the selected mode based on command line args. """
    if args.action == 'hash-password':
        # TODO(cmaloney): Import a function from the auth stuff to do the hashing and guarantee it
        # always matches
        byte_str = do_hash_password(args.password).encode('ascii')
        sys.stdout.buffer.write(byte_str + b'\n')
        sys.exit(0)

    if args.action == 'generate-node-upgrade-script':
        status = backend.generate_node_upgrade_script(args.installed_cluster_version)
        sys.exit(status)

    if args.action in dispatch_dict_simple:
        action = dispatch_dict_simple[args.action]
        if action[1] is not None:
            print_header(action[1])
        sys.exit(action[0](args))

    print("Internal Error: No known way to dispatch {}".format(args.action))
    sys.exit(1)


class ArgsAction(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):
        assert self.option_strings[0][:2] == '--'
        setattr(namespace, 'action', self.option_strings[0][2:])
        setattr(namespace, self.dest, values)


def get_argument_parser():
    """
    Parse CLI arguments and return a map of options.
    """
    parser = argparse.ArgumentParser(
        description="DC/OS Install and Configuration Utility")
    mutual_exc = parser.add_mutually_exclusive_group()

    return 0


dispatch_dict_simple = {
    'version': (do_version, None, 'Print the DC/OS version'),
    'web': (
        dcos_installer.async_server.start,
        'Starting DC/OS installer in web mode',
        'Run the web interface'),
    'genconf': (
    )

    parser.add_argument(
        '-v',
        '--verbose',
        action='store_true',
        help='Verbose log output (DEBUG).')

    parser.add_argument(
        '-p',
        '--port',
        type=int,
        default=9000,
        help=argparse.SUPPRESS)

    def add_mode(name, help_msg):
        mutual_exc.add_argument(
            '--{}'.format(name),
            action='store_const',
            const=name,
            dest='action',
            help=help_msg)

    # Add all arg modes
    for name, value in dispatch_dict_simple.items():
        add_mode(name, value[2])

    parser.set_defaults(action='genconf')

    return parser


def main():
    # Passd in by installer_internal_wrapper since in ash exec can't set argv0
    # directly to not be the name of the binary being executed.
    if 'INSTALLER_ARGV0' in os.environ:
        sys.argv[0] = os.environ['INSTALLER_ARGV0']
    argument_parser = get_argument_parser()

    try:
        options = argument_parser.parse_args()
        setup_logger(options)
        dispatch(options)
    except dcos_installer.config.NoConfigError as ex:
        print(ex)
        sys.exit(1)


if __name__ == '__main__':
    main()

<MSG> Exit with error if --web is passed to installer

<DFF> @@ -8,7 +8,6 @@ import sys
 import coloredlogs
 from passlib.hash import sha512_crypt
 
-import dcos_installer.async_server
 import dcos_installer.config
 import dcos_installer.constants
 import gen.calc
@@ -127,10 +126,16 @@ def do_validate_config(args):
     return 0
 
 
+def web_installer(options):
+    log.error('The DC/OS web installer (--web) has been removed.\n'
+              'Please refer to the DC/OS Installation guide at https://docs.mesosphere.com/1.12/installing/')
+    sys.exit(1)
+
+
 dispatch_dict_simple = {
     'version': (do_version, None, 'Print the DC/OS version'),
     'web': (
-        dcos_installer.async_server.start,
+        web_installer,
         'Starting DC/OS installer in web mode',
         'Run the web interface'),
     'genconf': (

{'commit': "diff --git a/dcos_installer/cli.py b/dcos_installer/cli.py\nindex 42e4e713..c7aef7ad 100644\n--- a/dcos_installer/cli.py\n+++ b/dcos_installer/cli.py\n@@ -8,7 +8,6 @@ import sys\n import coloredlogs\n from passlib.hash import sha512_crypt\n \n-import dcos_installer.async_server\n import dcos_installer.config\n import dcos_installer.constants\n import gen.calc\n@@ -127,10 +126,16 @@ def do_validate_config(args):\n     return 0\n \n \n+def web_installer(options):\n+    log.error('The DC/OS web installer (--web) has been removed.\\n'\n+              'Please refer to the DC/OS Installation guide at https://docs.mesosphere.com/1.12/installing/')\n+    sys.exit(1)\n+\n+\n dispatch_dict_simple = {\n     'version': (do_version, None, 'Print the DC/OS version'),\n     'web': (\n-        dcos_installer.async_server.start,\n+        web_installer,\n         'Starting DC/OS installer in web mode',\n         'Run the web interface'),\n     'genconf': (\n", 'commit_subject': 'Exit with error if --web is passed to installer', 'repo_name': 'dcos/dcos', 'committer': {'name': 'Branden Rolston', 'email': 'b90ccaea86a51c96cec5e5e5c7ce88bb84f906c3@mesosphere.com', 'time_sec': '1526672804', 'tz_offset': '-420', 'date': {'seconds': '1526672804'}}, 'commit_tree': '95c48ddd61bc91c616e0299e478ceff2c932b61b', 'commit_message': 'Exit with error if --web is passed to installer\n', 'language_name': 'HTML', 'license': 'apache-2.0', 'hunks': "@@ -8,7 +8,6 @@ import sys\n import coloredlogs\n from passlib.hash import sha512_crypt\n \n-import dcos_installer.async_server\n import dcos_installer.config\n import dcos_installer.constants\n import gen.calc\n@@ -127,10 +126,16 @@ def do_validate_config(args):\n     return 0\n \n \n+def web_installer(options):\n+    log.error('The DC/OS web installer (--web) has been removed.\\n'\n+              'Please refer to the DC/OS Installation guide at https://docs.mesosphere.com/1.12/installing/')\n+    sys.exit(1)\n+\n+\n dispatch_dict_simple = {\n     'version': (do_version, None, 'Print the DC/OS version'),\n     'web': (\n-        dcos_installer.async_server.start,\n+        web_installer,\n         'Starting DC/OS installer in web mode',\n         'Run the web interface'),\n     'genconf': (\n", 'addition_count': 7, 'deletion_count': 2, 'src_file': 'a/dcos_installer/cli.py', 'tgt_file': 'b/dcos_installer/cli.py', 'file_extension': '.py', 'before_file': 'import argparse\nimport json\nimport logging\nimport os\nimport sys\n\nimport coloredlogs\nimport coloredlogs\nfrom passlib.hash import sha512_crypt\n\nimport dcos_installer.async_server\nimport dcos_installer.config\nimport dcos_installer.constants\nimport gen.calc\nfrom dcos_installer.prettyprint import print_header\n\nlog = logging.getLogger(__name__)\n\n\ndef setup_logger(options):\n    level = \'INFO\'\n    if options.verbose:\n        level = \'DEBUG\'\n    coloredlogs.install(\n        level=level,\n        level_styles={\n            \'warn\': {\n                \'color\': \'yellow\'\n            },\n            \'error\': {\n                \'color\': \'red\',\n                \'bold\': True,\n            },\n        },\n        fmt=\'%(message)s\',\n        isatty=True\n    )\n    log.debug("Logger set to DEBUG")\n\n\ndef do_version(args):\n    print(json.dumps(\n        {\n            \'version\': gen.calc.entry[\'must\'][\'dcos_version\'],\n            \'variant\': os.environ[\'BOOTSTRAP_VARIANT\']},\n        indent=2, sort_keys=True))\n    return 0\n\n\ndef web_installer(options):\n    log.error(\'The DC/OS web installer (--web) has been removed.\\n\'\n              \'Please refer to the DC/OS Installation guide at https://docs.mesosphere.com/1.12/installing/\')\n    sys.exit(1)\n\n\ndispatch_dict_simple = {\n    \'version\': (do_version, None, \'Print the DC/OS version\'),\n    \'web\': (\n        web_installer,\n        \'Starting DC/OS installer in web mode\',\n        \'Run the web interface\'),\n    \'genconf\': (\n        lambda args: backend.do_configure(),\n        \'EXECUTING CONFIGURATION GENERATION\',\n        \'Create DC/OS install files customized according to {}.\'.format(dcos_installer.constants.CONFIG_PATH)),\n    \'aws-cloudformation\': (\n        lambda args: backend.do_aws_cf_configure(),\n        \'EXECUTING AWS CLOUD FORMATION TEMPLATE GENERATION\',\n        \'Generate AWS Advanced AWS CloudFormation templates using the provided config\')\n}\n\n\n# TODO(cmaloney): This should only be in enterprise / isn\'t useful in open currently.\ndef do_hash_password(password):\n    if password is None:\n        password = \'\'\n        while True:\n            password = input(\'Password: \')\n            if password:\n                break\n            else:\n                log.error(\'Must provide a non-empty password\')\n\n    print_header("HASHING PASSWORD TO SHA512")\n    hashed_password = sha512_crypt.encrypt(password)\n    return hashed_password\n\n\ndef dispatch(args):\n    """ Dispatches the selected mode based on command line args. """\n    if args.action == \'hash-password\':\n        # TODO(cmaloney): Import a function from the auth stuff to do the hashing and guarantee it\n        # always matches\n        byte_str = do_hash_password(args.password).encode(\'ascii\')\n        sys.stdout.buffer.write(byte_str + b\'\\n\')\n        sys.exit(0)\n\n    if args.action == \'generate-node-upgrade-script\':\n        status = backend.generate_node_upgrade_script(args.installed_cluster_version)\n        sys.exit(status)\n\n    if args.action in dispatch_dict_simple:\n        action = dispatch_dict_simple[args.action]\n        if action[1] is not None:\n            print_header(action[1])\n        sys.exit(action[0](args))\n\n    print("Internal Error: No known way to dispatch {}".format(args.action))\n    sys.exit(1)\n\n\nclass ArgsAction(argparse.Action):\n    def __call__(self, parser, namespace, values, option_string=None):\n        assert self.option_strings[0][:2] == \'--\'\n        setattr(namespace, \'action\', self.option_strings[0][2:])\n        setattr(namespace, self.dest, values)\n\n\ndef get_argument_parser():\n    """\n    Parse CLI arguments and return a map of options.\n    """\n    parser = argparse.ArgumentParser(\n        description="DC/OS Install and Configuration Utility")\n    mutual_exc = parser.add_mutually_exclusive_group()\n\n    return 0\n\n\ndispatch_dict_simple = {\n    \'version\': (do_version, None, \'Print the DC/OS version\'),\n    \'web\': (\n        dcos_installer.async_server.start,\n        \'Starting DC/OS installer in web mode\',\n        \'Run the web interface\'),\n    \'genconf\': (\n    )\n\n    parser.add_argument(\n        \'-v\',\n        \'--verbose\',\n        action=\'store_true\',\n        help=\'Verbose log output (DEBUG).\')\n\n    parser.add_argument(\n        \'-p\',\n        \'--port\',\n        type=int,\n        default=9000,\n        help=argparse.SUPPRESS)\n\n    def add_mode(name, help_msg):\n        mutual_exc.add_argument(\n            \'--{}\'.format(name),\n            action=\'store_const\',\n            const=name,\n            dest=\'action\',\n            help=help_msg)\n\n    # Add all arg modes\n    for name, value in dispatch_dict_simple.items():\n        add_mode(name, value[2])\n\n    parser.set_defaults(action=\'genconf\')\n\n    return parser\n\n\ndef main():\n    # Passd in by installer_internal_wrapper since in ash exec can\'t set argv0\n    # directly to not be the name of the binary being executed.\n    if \'INSTALLER_ARGV0\' in os.environ:\n        sys.argv[0] = os.environ[\'INSTALLER_ARGV0\']\n    argument_parser = get_argument_parser()\n\n    try:\n        options = argument_parser.parse_args()\n        setup_logger(options)\n        dispatch(options)\n    except dcos_installer.config.NoConfigError as ex:\n        print(ex)\n        sys.exit(1)\n\n\nif __name__ == \'__main__\':\n    main()\n', 'message': 'Exit with error if --web is passed to installer\n', 'author_name': 'Branden Rolston', 'lang': 'py'}