Example #1
0
def test_do_configure_logs_validation_errors(tmpdir, monkeypatch, caplog):
    """
    Configuration validation errors are logged as `error` messages.
    """
    monkeypatch.setenv('BOOTSTRAP_VARIANT', 'test_variant')
    invalid_config = textwrap.dedent("""---
    cluster_name: DC/OS
    master_discovery: static
    # Remove `exhibitor_storage_backend` from configuration
    # exhibitor_storage_backend: static
    master_list:
    - 127.0.0.1
    bootstrap_url: http://example.com
    """)
    create_config(invalid_config, tmpdir)
    create_fake_build_artifacts(tmpdir)
    with tmpdir.as_cwd():
        assert backend.do_configure(config_path='genconf/config.yaml') == 1

    expected_error_message = (
        'exhibitor_storage_backend: Must set exhibitor_storage_backend, '
        'no way to calculate value.')
    error_logs = [
        rec for rec in caplog.records if rec.message == expected_error_message
    ]
    assert len(error_logs) == 1

    error_log = error_logs[0]
    assert error_log.levelno == logging.ERROR
Example #2
0
def test_do_configure_logs_validation_errors(tmpdir, monkeypatch, caplog):
    """
    Configuration validation errors are logged as `error` messages.
    """
    monkeypatch.setenv('BOOTSTRAP_VARIANT', 'test_variant')
    invalid_config = textwrap.dedent("""---
    cluster_name: DC/OS
    master_discovery: static
    # Remove `exhibitor_storage_backend` from configuration
    # exhibitor_storage_backend: static
    master_list:
    - 127.0.0.1
    bootstrap_url: http://example.com
    """)
    create_config(invalid_config, tmpdir)
    create_fake_build_artifacts(tmpdir)
    with tmpdir.as_cwd():
        assert backend.do_configure(config_path='genconf/config.yaml') == 1

    expected_error_message = (
        'exhibitor_storage_backend: Must set exhibitor_storage_backend, '
        'no way to calculate value.'
    )
    error_logs = [rec for rec in caplog.records if rec.message == expected_error_message]
    assert len(error_logs) == 1

    error_log = error_logs[0]
    assert error_log.levelno == logging.ERROR
def test_do_configure(tmpdir):
    genconf_dir = tmpdir.join('genconf')
    genconf_dir.ensure(dir=True)
    config_path = genconf_dir.join('config.yaml')
    config_path.write(simple_full_config)
    genconf_dir.join('ip-detect').write('#!/bin/bash\necho 127.0.0.1')
    tmpdir.join('artifacts/bootstrap/12345.bootstrap.tar.xz').write('contents_of_bootstrap', ensure=True)
    tmpdir.join('artifacts/bootstrap/12345.active.json').write('{"active": "contents"}', ensure=True)

    with tmpdir.as_cwd():
        assert backend.do_configure(config_path=str(config_path)) == 0
Example #4
0
def test_do_configure_valid_config_no_duplicate_logging(tmpdir, monkeypatch, caplog):
    """
    Log messages are logged exactly once.
    """
    monkeypatch.setenv('BOOTSTRAP_VARIANT', 'test_variant')
    create_config(simple_full_config, tmpdir)
    create_fake_build_artifacts(tmpdir)
    with tmpdir.as_cwd():
        assert backend.do_configure(config_path='genconf/config.yaml') == 0

    # The message comes from gen.get_dcosconfig_source_target_and_templates() function
    expected_message = 'Generating configuration files...'
    filtered_messages = [rec.message for rec in caplog.records if rec.message == expected_message]
    assert [expected_message] == filtered_messages
Example #5
0
def test_do_configure_valid_config_no_duplicate_logging(tmpdir, monkeypatch, caplog):
    """
    Log messages are logged exactly once.
    """
    monkeypatch.setenv('BOOTSTRAP_VARIANT', 'test_variant')
    create_config(simple_full_config, tmpdir)
    create_fake_build_artifacts(tmpdir)
    with tmpdir.as_cwd():
        assert backend.do_configure(config_path='genconf/config.yaml') == 0

    # The message comes from gen.get_dcosconfig_source_target_and_templates() function
    expected_message = 'Generating configuration files...'
    filtered_messages = [rec.message for rec in caplog.records if rec.message == expected_message]
    assert [expected_message] == filtered_messages
Example #6
0
    def __init__(self, args=None):
        """
        The web based installer leverages Flask to present end-users of
        dcos_installer with a clean web interface to configure their
        site-based installation of DC/OS.
        """
        # If no args are passed to the class, then we're calling this
        # class from another library or code so we shouldn't execute
        # parser or anything else
        if args:
            options = self.parse_args(args)
            if len(options.hash_password) > 0:
                print_header("HASHING PASSWORD TO SHA512")
                backend.hash_password(options.hash_password)
                sys.exit(0)

            make_default_dir()

            if options.web:
                print_header("Starting DC/OS installer in web mode")
                async_server.start(options)

            if options.validate_config:
                print_header('VALIDATING CONFIGURATION')
                log_warn_only()
                validation_errors = backend.do_validate_gen_config()
                if validation_errors:
                    print_validation_errors(validation_errors)
                    sys.exit(1)
                sys.exit(0)

            if options.genconf:
                print_header("EXECUTING CONFIGURATION GENERATION")
                code = backend.do_configure()
                if code != 0:
                    sys.exit(1)
                sys.exit(0)

            validate_ssh_config_or_exit()

            dispatch_action(options)
Example #7
0
def action_action_name(request):
    """Return /action/<action_name>

    :param request: a web requeest object.
    :type request: request | None
    """
    action_name = request.match_info['action_name']

    # Update the global action
    json_state = read_json_state(action_name)
    app['current_action'] = action_name

    if request.method == 'GET':
        log.info('GET {}'.format(action_name))

        if json_state:
            return web.json_response(json_state)
        return web.json_response({})

    elif request.method == 'POST':
        log.info('POST {}'.format(action_name))
        action = action_map.get(action_name)
        # If the action name is preflight, attempt to run configuration
        # generation. If genconf fails, present the UI with a usable error
        # for the end-user
        if action_name == 'preflight':
            try:
                print_header("GENERATING CONFIGURATION")
                backend.do_configure()
            except:
                genconf_failure = {
                    "errors": "Configuration generation failed, please see command line for details"
                }
                return web.json_response(genconf_failure, status=400)

        params = yield from request.post()

        if json_state:
            if action_name == 'deploy' and 'retry' in params:
                if 'hosts' in json_state:
                    failed_hosts = []
                    for deploy_host, deploy_params in json_state['hosts'].items():
                        if deploy_params['host_status'] != 'success':
                            failed_hosts.append(Node(deploy_host, tags=deploy_params['tags']))
                    log.debug('failed hosts: {}'.format(failed_hosts))
                    if failed_hosts:
                        yield from asyncio.async(
                            action(
                                backend.get_config(),
                                state_json_dir=STATE_DIR,
                                hosts=failed_hosts,
                                try_remove_stale_dcos=True,
                                **params))
                        return web.json_response({
                            'status': 'retried',
                            'details': sorted(['{}:{}'.format(node.ip, node.port) for node in failed_hosts])
                        })

            if action_name not in remove_on_done:
                return web.json_response({'status': '{} was already executed, skipping'.format(action_name)})

            running = False
            for host, attributes in json_state['hosts'].items():
                if attributes['host_status'].lower() == 'running':
                    running = True

            log.debug('is action running: {}'.format(running))
            if running:
                return web.json_response({'status': '{} is running, skipping'.format(action_name)})
            else:
                unlink_state_file(action_name)

        yield from asyncio.async(action(backend.get_config(), state_json_dir=STATE_DIR, options=options, **params))
        return web.json_response({'status': '{} started'.format(action_name)})
Example #8
0
def test_do_configure(tmpdir, monkeypatch):
    monkeypatch.setenv('BOOTSTRAP_VARIANT', 'test_variant')
    create_config(simple_full_config, tmpdir)
    create_fake_build_artifacts(tmpdir)
    with tmpdir.as_cwd():
        assert backend.do_configure(config_path='genconf/config.yaml') == 0
Example #9
0
File: cli.py Project: zouyee/dcos
    return 0


def do_uninstall(*args, **kwargs):
    tall_enough_to_ride()
    return action_lib.uninstall_dcos(*args, **kwargs)


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': (
        lambda args: backend.do_configure(),
        'EXECUTING CONFIGURATION GENERATION',
        'Execute the configuration generation (genconf).'),
    'validate-config': (
        do_validate_config,
        'VALIDATING CONFIGURATION',
        'Validate the configuration for executing --genconf and deploy arguments in config.yaml'),
    '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')
}

dispatch_dict_aio = {
    'preflight': (
        action_lib.run_preflight,
Example #10
0
def action_action_name(request):
    """Return /action/<action_name>

    :param request: a web requeest object.
    :type request: request | None
    """
    global current_action
    action_name = request.match_info['action_name']

    # Update the global action
    json_state = read_json_state(action_name)
    current_action = action_name

    if request.method == 'GET':
        log.info('GET {}'.format(action_name))

        if json_state:
            return web.json_response(json_state)
        return web.json_response({})

    elif request.method == 'POST':
        log.info('POST {}'.format(action_name))
        action = action_map.get(action_name)
        # If the action name is preflight, attempt to run configuration
        # generation. If genconf fails, present the UI with a usable error
        # for the end-user
        if action_name == 'preflight':
            try:
                log.warning("GENERATING CONFIGURATION")
                backend.do_configure()
            except:
                genconf_failure = {
                    "errors": "Configuration generation failed, please see command line for details"
                }
                return web.json_response(genconf_failure, status=400)

        params = yield from request.post()

        if json_state:
            if action_name == 'deploy' and 'retry' in params:
                if 'hosts' in json_state:
                    failed_hosts = []
                    for deploy_host, deploy_params in json_state['hosts'].items():
                        if deploy_params['host_status'] != 'success':
                            failed_hosts.append(Node(deploy_host, tags=deploy_params['tags']))
                    log.debug('failed hosts: {}'.format(failed_hosts))
                    if failed_hosts:
                        yield from asyncio.async(
                            action(
                                backend.get_config(),
                                state_json_dir=STATE_DIR,
                                hosts=failed_hosts,
                                try_remove_stale_dcos=True,
                                **params))
                        return web.json_response({
                            'status': 'retried',
                            'details': sorted(['{}:{}'.format(node.ip, node.port) for node in failed_hosts])
                        })

            if action_name not in remove_on_done:
                return web.json_response({'status': '{} was already executed, skipping'.format(action_name)})

            running = False
            for host, attributes in json_state['hosts'].items():
                if attributes['host_status'].lower() == 'running':
                    running = True

            log.debug('is action running: {}'.format(running))
            if running:
                return web.json_response({'status': '{} is running, skipping'.format(action_name)})
            else:
                unlink_state_file(action_name)

        yield from asyncio.async(action(backend.get_config(), state_json_dir=STATE_DIR, options=options, **params))
        return web.json_response({'status': '{} started'.format(action_name)})
Example #11
0
        print_validation_errors(validation_errors)
        return 1
    return 0


def do_uninstall(*args, **kwargs):
    tall_enough_to_ride()
    return action_lib.uninstall_dcos(*args, **kwargs)


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':
    (lambda args: backend.do_configure(), 'EXECUTING CONFIGURATION GENERATION'
     'Execute the configuration generation (genconf).'),
    'validate-config':
    (do_validate_config, 'VALIDATING CONFIGURATION',
     'Validate the configuration for executing --genconf and deploy arguments in config.yaml'
     ),
    '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'
     )
}

dispatch_dict_aio = {
    'preflight': (action_lib.run_preflight, 'EXECUTING_PREFLIGHT',
                  'Execute the preflight checks on a series of nodes.'),
Example #12
0
def test_do_configure(tmpdir, monkeypatch):
    monkeypatch.setenv('BOOTSTRAP_VARIANT', 'test_variant')
    create_config(simple_full_config, tmpdir)
    create_fake_build_artifacts(tmpdir)
    with tmpdir.as_cwd():
        assert backend.do_configure(config_path='genconf/config.yaml') == 0
 def genconf(args):
     print_header("EXECUTING CONFIGURATION GENERATION")
     code = backend.do_configure()
     if code != 0:
         return 1
     return 0
Example #14
0
File: cli.py Project: kaysoky/dcos
def do_genconf(args):
    print_header("EXECUTING CONFIGURATION GENERATION")
    code = backend.do_configure()
    if code != 0:
        return 1
    return 0
Example #15
0
    def __init__(self, args=None):
        """
        The web based installer leverages Flask to present end-users of
        dcos_installer with a clean web interface to configure their
        site-based installation of DC/OS.
        """
        # If no args are passed to the class, then we're calling this
        # class from another library or code so we shouldn't execute
        # parser or anything else
        make_default_dir()
        if args:
            options = self.parse_args(args)
            if len(options.hash_password) > 0:
                print_header("HASHING PASSWORD TO SHA512")
                backend.hash_password(options.hash_password)
                sys.exit(0)

            if options.web:
                print_header("Starting DC/OS installer in web mode")
                async_server.start(options)

            if options.genconf:
                print_header("EXECUTING CONFIGURATION GENERATION")
                code = backend.do_configure()
                if code != 0:
                    sys.exit(1)
                sys.exit(0)

            if options.validate_config:
                print_header('VALIDATING CONFIGURATION')
                log_warn_only()
                validation_errors = backend.do_validate_gen_config()
                if validation_errors:
                    print_validation_errors(validation_errors)
                    sys.exit(1)
                sys.exit(0)

            validate_ssh_config_or_exit()
            action = None

            if options.preflight:
                print_header("EXECUTING PREFLIGHT")
                action = action_lib.run_preflight

            if options.deploy:
                print_header("EXECUTING DC/OS INSTALLATION")
                action = action_lib.install_dcos

            if options.postflight:
                print_header("EXECUTING POSTFLIGHT")
                action = action_lib.run_postflight

            if options.uninstall:
                print_header("EXECUTING UNINSTALL")
                tall_enough_to_ride()
                action = action_lib.uninstall_dcos

            if options.install_prereqs:
                print_header("EXECUTING INSTALL PREREQUISITES")
                action = action_lib.install_prereqs

            sys.exit(run_loop(action, options))