Example #1
0
def update_marathon_client():
    global client
    global toml_config_o
    toml_config_o = config.get_config()
    dcos_url = config.get_config_val('core.dcos_url', toml_config_o)
    marathon_url = urllib.parse.urljoin(dcos_url, 'service/marathon-user/')
    config.set_val('marathon.url', marathon_url)
    toml_config_m = config.get_config()
    client = marathon.create_client(toml_config_m)
Example #2
0
def test_get_config(load_path_mock):
    with env(), util.tempdir() as tempdir:
        os.environ.pop('DCOS_CONFIG', None)
        os.environ[constants.DCOS_DIR_ENV] = tempdir

        # no config file of any type
        # this should create the global config
        config.get_config()
        global_toml = os.path.join(tempdir, "dcos.toml")
        load_path_mock.assert_called_once_with(global_toml, False)
        load_path_mock.reset_mock()

        # create old global config toml
        global_toml = create_global_config(tempdir)
        config.get_config()
        load_path_mock.assert_called_once_with(global_toml, False)
        load_path_mock.reset_mock()

        # clusters dir, no clusters
        _create_clusters_dir(tempdir)
        config.get_config()
        load_path_mock.assert_called_once_with(global_toml, False)
        load_path_mock.reset_mock()

        cluster_id = "fake-cluster"
        cluster_path = add_cluster_dir(cluster_id, tempdir)
        cluster_toml = os.path.join(cluster_path, "dcos.toml")
        config.get_config(True)
        load_path_mock.assert_called_with(cluster_toml, True)
Example #3
0
def test_get_config(load_path_mock):
    with env(), util.tempdir() as tempdir:
        os.environ.pop('DCOS_CONFIG', None)
        os.environ[constants.DCOS_DIR_ENV] = tempdir

        # no config file of any type
        with pytest.raises(DCOSException) as e:
            config.get_config()

        msg = ("No cluster is attached. "
               "Please run `dcos cluster attach <cluster-name>`")
        assert str(e.value) == msg
        load_path_mock.assert_not_called()

        # create old global config toml
        global_toml = create_global_config(tempdir)
        config.get_config()
        load_path_mock.assert_called_once_with(global_toml, False)

        # clusters dir, no clusters
        _create_clusters_dir(tempdir)
        with pytest.raises(DCOSException) as e:
            config.get_config()
        assert str(e.value) == msg

        cluster_id = "fake-cluster"
        cluster_path = add_cluster_dir(cluster_id, tempdir)
        cluster_toml = os.path.join(cluster_path, "dcos.toml")
        config.get_config(True)
        load_path_mock.assert_any_call(cluster_toml, True)
Example #4
0
def _main():
    signal.signal(signal.SIGINT, signal_handler)

    http.silence_requests_warnings()
    toml_config = config.get_config()
    set_ssl_info_env_vars(toml_config)

    args = docopt.docopt(default_doc("dcos"), options_first=True)

    log_level = args['--log-level']
    if log_level and not _config_log_level_environ(log_level):
        return 1

    if args['--debug']:
        os.environ[constants.DCOS_DEBUG_ENV] = 'true'

    util.configure_process_from_environ()

    if args['--version']:
        return _get_versions(toml_config.get("core.dcos_url"))

    command = args['<command>']

    if not command:
        command = "help"

    if command in subcommand.default_subcommands():
        sc = SubcommandMain(command, args['<args>'])
    else:
        executable = subcommand.command_executables(command)
        sc = subcommand.SubcommandProcess(
            executable, command, args['<args>'])

    exitcode, _ = sc.run_and_capture()
    return exitcode
Example #5
0
def get_spark_dispatcher():
    dcos_spark_url = os.getenv("DCOS_SPARK_URL")
    if dcos_spark_url is not None:
        return dcos_spark_url

    base_url = config.get_config().get('core.dcos_url')
    return urllib.parse.urljoin(base_url, '/service/' + service.app_id() + '/')
Example #6
0
def _is_request_to_dcos(url, toml_config=None):
    """Checks if a request is for the DC/OS cluster.

    :param url: URL of the request
    :type url: str
    :param toml_config: cluster config to use
    :type toml_config: Toml
    :return: whether the request is for the cluster
    :rtype: bool
    """

    if toml_config is None:
        toml_config = config.get_config()

    dcos_url = urlparse(config.get_config_val("core.dcos_url", toml_config))
    cosmos_url = urlparse(
        config.get_config_val("package.cosmos_url", toml_config))
    parsed_url = urlparse(url)

    # request should match scheme + netloc
    def _request_match(expected_url, actual_url):
        return expected_url.scheme == actual_url.scheme and \
                    expected_url.netloc == actual_url.netloc

    is_request_to_cluster = _request_match(dcos_url, parsed_url) or \
        _request_match(cosmos_url, parsed_url)

    return is_request_to_cluster
Example #7
0
def get_spark_dispatcher():
    dcos_spark_url = os.getenv("DCOS_SPARK_URL")
    if dcos_spark_url is not None:
        return dcos_spark_url

    base_url = config.get_config().get("core.dcos_url")
    return urllib.parse.urljoin(base_url, "/service/" + service.app_id() + "/")
Example #8
0
def _login():
    """
    :returns: process status
    :rtype: int
    """

    # every call to login will generate a new token if applicable
    _logout()
    conf = config.get_config()
    dcos_url = conf.get("core.dcos_url")
    if dcos_url is None:
        msg = ("Please provide the url to your DCOS cluster: "
               "`dcos config set core.dcos_url`")
        raise DCOSException(msg)

    # hit protected endpoint which will prompt for auth if cluster has auth
    try:
        url = urllib.parse.urljoin(dcos_url, 'exhibitor')
        http.get(url)
    # if the user is authenticated, they have effectively "logged in" even if
    # they are not authorized for this endpoint
    except DCOSAuthorizationException:
        pass

    emitter.publish("Login successful!")
    return 0
Example #9
0
    def __init__(self, toml_config: Optional[Any] = None):
        super(DCOSClient, self).__init__()
        self.toml_config = toml_config
        if toml_config is None:
            self.toml_config = config.get_config()

        self._dcos_url = cast(ParseResult, urlparse(config.get_config_val("core.dcos_url", toml_config)))
Example #10
0
def _get_dcos_auth(auth_scheme, username, password, hostname):
    """Get authentication flow for dcos acs auth and dcos oauth

    :param auth_scheme: authentication_scheme
    :type auth_scheme: str
    :param username: username user for authentication
    :type username: str
    :param password: password for authentication
    :type password: str
    :param hostname: hostname for credentials
    :type hostname: str
    :returns: DCOSAcsAuth
    :rtype: AuthBase
    """

    toml_config = config.get_config()
    token = config.get_config_val("core.dcos_acs_token", toml_config)
    if token is None:
        dcos_url = config.get_config_val("core.dcos_url", toml_config)
        if auth_scheme == "acsjwt":
            creds = _get_dcos_acs_auth_creds(username, password, hostname)
        else:
            creds = _get_dcos_oauth_creds(dcos_url)

        url = urllib.parse.urljoin(dcos_url, 'acs/api/v1/auth/login')
        response = _request('post', url, json=creds)

        if response.status_code == 200:
            token = response.json()['token']
            config.set_val("core.dcos_acs_token", token)

    return DCOSAcsAuth(token)
Example #11
0
    def overlay_info(self):
        # XXX This methodology is copied from the dcos.mesos package, this can
        # be removed once the upstream package has support for this field.

        url = self.dcos_client.master_url('overlay-agent/overlay')
        timeout = dcosconfig.get_config_val('core.timeout', dcosconfig.get_config())
        return dcoshttp.get(url, timeout=timeout).json()
Example #12
0
def _page(output, pager_command=None):
    """Conditionally pipes the supplied output through a pager.

    :param output:
    :type output: object
    :param pager_command:
    :type pager_command: str
    """

    output = six.text_type(output)

    if pager_command is None:
        pager_command = 'less -R'

    if not sys.stdout.isatty() or util.is_windows_platform():
        print(output)
        return

    num_lines = output.count('\n')
    exceeds_tty_height = pager.getheight() - 1 < num_lines

    paginate = config.get_config().get("core.pagination", True)
    if exceeds_tty_height and paginate:
        pydoc.pipepager(output, cmd=pager_command)
    else:
        print(output)
Example #13
0
def _verify_ssl(url, verify=None, toml_config=None):
    """Returns whether to verify ssl for the given url

    :param url: the target URL
    :type url: str
    :param verify: whether to verify SSL certs or path to cert(s)
    :type verify: bool | str
    :param toml_config: cluster config to use
    :type toml_config: Toml
    :return: whether to verify SSL certs or path to cert(s)
    :rtype: bool | str
    """

    if not _is_request_to_dcos(url, toml_config):
        # Leave verify to None if URL is outside the DC/OS cluster
        # https://jira.mesosphere.com/browse/DCOS_OSS-618
        return None

    if toml_config is None:
        toml_config = config.get_config()

    if verify is None:
        verify = config.get_config_val("core.ssl_verify", toml_config)
        if verify and verify.lower() == "true":
            verify = True
        elif verify and verify.lower() == "false":
            verify = False

    return verify
Example #14
0
    def overlay_info(self):
        # XXX This methodology is copied from the dcos.mesos package, this can
        # be removed once the upstream package has support for this field.

        url = self.dcos_client.master_url('overlay-agent/overlay')
        timeout = dcosconfig.get_config_val('core.timeout',
                                            dcosconfig.get_config())
        return dcoshttp.get(url, timeout=timeout).json()
Example #15
0
def request(method,
            url,
            is_success=_default_is_success,
            timeout=None,
            verify=None,
            **kwargs):
    """Sends an HTTP request. If the server responds with a 401, ask the
    user for their credentials, and try request again (up to 3 times).

    :param method: method for the new Request object
    :type method: str
    :param url: URL for the new Request object
    :type url: str
    :param is_success: Defines successful status codes for the request
    :type is_success: Function from int to bool
    :param timeout: request timeout
    :type timeout: int
    :param verify: whether to verify SSL certs or path to cert(s)
    :type verify: bool | str
    :param kwargs: Additional arguments to requests.request
        (see http://docs.python-requests.org/en/latest/api/#requests.request)
    :type kwargs: dict
    :rtype: Response
    """

    toml_config = config.get_config()
    auth_token = config.get_config_val("core.dcos_acs_token", toml_config)
    dcos_url = urlparse(config.get_config_val("core.dcos_url", toml_config))
    parsed_url = urlparse(url)

    # only request with DC/OS Auth if request is to DC/OS cluster
    # request should match scheme + netloc
    scheme_eq = parsed_url.scheme == dcos_url.scheme
    netloc_eq = parsed_url.netloc == dcos_url.netloc
    if auth_token and scheme_eq and netloc_eq:
        auth = DCOSAcsAuth(auth_token)
    else:
        auth = None
    response = _request(method, url, is_success, timeout,
                        auth=auth, verify=verify, **kwargs)

    if is_success(response.status_code):
        return response
    elif response.status_code == 401:
        if auth_token is not None:
            msg = ("Your core.dcos_acs_token is invalid. "
                   "Please run: `dcos auth login`")
            raise DCOSAuthenticationException(msg)
        else:
            raise DCOSAuthenticationException(response)
    elif response.status_code == 422:
        raise DCOSUnprocessableException(response)
    elif response.status_code == 403:
        raise DCOSAuthorizationException(response)
    elif response.status_code == 400:
        raise DCOSBadRequest(response)
    else:
        raise DCOSHTTPException(response)
Example #16
0
    def __init__(self):
        toml_config = config.get_config()

        self._dcos_url = toml_config.get("core.dcos_url")
        if self._dcos_url is None:
            raise config.missing_config_exception(['core.dcos_url'])
        self._mesos_master_url = toml_config.get('core.mesos_master_url')

        self._timeout = toml_config.get('core.timeout')
Example #17
0
def dcos_config():
    """ Context manager for altering the toml
    """

    toml_config_o = config.get_config()
    try:
        yield
    finally:
        # return config to previous state
        config.save(toml_config_o)
Example #18
0
    def __init__(self):
        toml_config = config.get_config()

        self._dcos_url = config.get_config_val("core.dcos_url", toml_config)
        if self._dcos_url is None:
            raise config.missing_config_exception(['core.dcos_url'])
        self._mesos_master_url = config.get_config_val('core.mesos_master_url',
                                                       toml_config)

        self._timeout = config.get_config_val('core.timeout', toml_config)
Example #19
0
def _logout():
    """
    Logout the user from dcos acs auth or oauth

    :returns: process status
    :rtype: int
    """

    if config.get_config().get("core.dcos_acs_token") is not None:
        config.unset("core.dcos_acs_token")
    return 0
Example #20
0
def get_cosmos_url():
    """
    :returns: cosmos base url
    :rtype: str
    """
    toml_config = config.get_config()
    cosmos_url = config.get_config_val("package.cosmos_url", toml_config)
    if cosmos_url is None:
        cosmos_url = config.get_config_val("core.dcos_url", toml_config)
        if cosmos_url is None:
            raise config.missing_config_exception(["core.dcos_url"])
    return cosmos_url
Example #21
0
def get_cosmos_url():
    """
    :returns: cosmos base url
    :rtype: str
    """
    toml_config = config.get_config()
    cosmos_url = config.get_config_val("package.cosmos_url", toml_config)
    if cosmos_url is None:
        cosmos_url = config.get_config_val("core.dcos_url", toml_config)
        if cosmos_url is None:
            raise config.missing_config_exception(["core.dcos_url"])
    return cosmos_url
Example #22
0
def request(method,
            url,
            is_success=_default_is_success,
            timeout=None,
            verify=None,
            **kwargs):
    """Sends an HTTP request. If the server responds with a 401, ask the
    user for their credentials, and try request again (up to 3 times).

    :param method: method for the new Request object
    :type method: str
    :param url: URL for the new Request object
    :type url: str
    :param is_success: Defines successful status codes for the request
    :type is_success: Function from int to bool
    :param timeout: request timeout
    :type timeout: int
    :param verify: whether to verify SSL certs or path to cert(s)
    :type verify: bool | str
    :param kwargs: Additional arguments to requests.request
        (see http://docs.python-requests.org/en/latest/api/#requests.request)
    :type kwargs: dict
    :rtype: Response
    """

    auth_token = config.get_config_val(
        "core.dcos_acs_token", config.get_config())
    if auth_token is None:
        auth = None
    else:
        auth = DCOSAcsAuth(auth_token)
    response = _request(method, url, is_success, timeout,
                        auth=auth, verify=verify, **kwargs)

    if is_success(response.status_code):
        return response
    elif response.status_code == 401:
        if auth_token is not None:
            msg = ("Your core.dcos_acs_token is invalid. "
                   "Please run: `dcos auth login`")
            raise DCOSException(msg)
        else:
            raise DCOSAuthenticationException(response)
    elif response.status_code == 422:
        raise DCOSUnprocessableException(response)
    elif response.status_code == 403:
        raise DCOSAuthorizationException(response)
    elif response.status_code == 400:
        raise DCOSBadRequest(response)
    else:
        raise DCOSHTTPException(response)
Example #23
0
def get_cosmos_url():
    """
    Gets the cosmos url

    :returns: cosmos base url
    :rtype: str
    """
    toml_config = config.get_config()
    cosmos_url = config.get_config_val('package.cosmos_url', toml_config)
    if cosmos_url is None:
        cosmos_url = config.get_config_val('core.dcos_url', toml_config)
        if cosmos_url is None:
            raise config.missing_config_exception(['core.dcos_url'])
    return cosmos_url
Example #24
0
def get_cosmos_url():
    """
    Gets the cosmos url

    :returns: cosmos base url
    :rtype: str
    """
    toml_config = config.get_config()
    cosmos_url = config.get_config_val('package.cosmos_url', toml_config)
    if cosmos_url is None:
        cosmos_url = config.get_config_val('core.dcos_url', toml_config)
        if cosmos_url is None:
            raise config.missing_config_exception(['core.dcos_url'])
    return cosmos_url
Example #25
0
def _get_default_base_url():
    """
    Gets the default service manager URL

    :returns: cosmos base url
    :rtype: str
    """
    toml_config = config.get_config()
    base_url = config.get_config_val('package.cosmos_url', toml_config)
    if base_url is None:
        base_url = config.get_config_val('core.dcos_url', toml_config)
        if base_url is None:
            raise config.missing_config_exception(['core.dcos_url'])
        else:
            base_url = urllib.parse.urljoin(base_url, 'cosmos/')
    return base_url
Example #26
0
def _get_default_base_url():
    """
    Gets the default service manager URL

    :returns: cosmos base url
    :rtype: str
    """
    toml_config = config.get_config()
    base_url = config.get_config_val('package.cosmos_url', toml_config)
    if base_url is None:
        base_url = config.get_config_val('core.dcos_url', toml_config)
        if base_url is None:
            raise config.missing_config_exception(['core.dcos_url'])
        else:
            base_url = urllib.parse.urljoin(base_url, 'cosmos/')
    return base_url
Example #27
0
def _validate():
    """
    :returns: process status
    :rtype: int
    """

    toml_config = config.get_config(True)

    errs = util.validate_json(toml_config._dictionary,
                              config.generate_root_schema(toml_config))
    if len(errs) != 0:
        emitter.publish(util.list_to_err(errs))
        return 1

    emitter.publish("Congratulations, your configuration is valid!")
    return 0
Example #28
0
def _validate():
    """
    :returns: process status
    :rtype: int
    """

    toml_config = config.get_config(True)

    errs = util.validate_json(toml_config._dictionary,
                              config.generate_root_schema(toml_config))
    if len(errs) != 0:
        emitter.publish(util.list_to_err(errs))
        return 1

    emitter.publish("Congratulations, your configuration is valid!")
    return 0
Example #29
0
def create_client(toml_config=None):
    """Creates a Marathon client with the supplied configuration.

    :param toml_config: configuration dictionary
    :type toml_config: config.Toml
    :returns: Marathon client
    :rtype: dcos.marathon.Client
    """

    if toml_config is None:
        toml_config = config.get_config()

    marathon_url = _get_marathon_url(toml_config)
    timeout = config.get_config_val('core.timeout') or http.DEFAULT_TIMEOUT

    logger.info('Creating marathon client with: %r', marathon_url)
    return Client(marathon_url, timeout=timeout)
Example #30
0
def marathon_on_marathon(name='marathon-user'):
    """ Context manager for altering the marathon client for MoM
    :param name: service name of MoM to use
    :type name: str
    """

    toml_config_o = config.get_config()
    dcos_url = config.get_config_val('core.dcos_url', toml_config_o)
    service_name = 'service/{}/'.format(name)
    marathon_url = urllib.parse.urljoin(dcos_url, service_name)
    config.set_val('marathon.url', marathon_url)

    try:
        yield
    finally:
        # return config to previous state
        config.save(toml_config_o)
Example #31
0
def create_client(toml_config=None):
    """Creates a Marathon client with the supplied configuration.

    :param toml_config: configuration dictionary
    :type toml_config: config.Toml
    :returns: Marathon client
    :rtype: dcos.marathon.Client
    """

    if toml_config is None:
        toml_config = config.get_config()

    marathon_url = _get_marathon_url(toml_config)
    timeout = config.get_config_val('core.timeout') or http.DEFAULT_TIMEOUT

    logger.info('Creating marathon client with: %r', marathon_url)
    return Client(marathon_url, timeout=timeout)
Example #32
0
def create_client(toml_config=None):
    """Creates a Metronome client with the supplied configuration.

    :param toml_config: configuration dictionary
    :type toml_config: config.Toml
    :returns: Metronome client
    :rtype: dcos.metronome.Client
    """

    if toml_config is None:
        toml_config = config.get_config()

    metronome_url = _get_metronome_url(toml_config)
    timeout = config.get_config_val('core.timeout') or http.DEFAULT_TIMEOUT
    rpc_client = rpcclient.create_client(metronome_url, timeout)

    logger.info('Creating metronome client with: %r', metronome_url)
    return Client(rpc_client)
Example #33
0
def create_client(toml_config=None):
    """Creates a Metronome client with the supplied configuration.

    :param toml_config: configuration dictionary
    :type toml_config: config.Toml
    :returns: Metronome client
    :rtype: dcos.metronome.Client
    """

    if toml_config is None:
        toml_config = config.get_config()

    metronome_url = _get_metronome_url(toml_config)
    timeout = config.get_config_val('core.timeout') or http.DEFAULT_TIMEOUT
    rpc_client = rpcclient.create_client(metronome_url, timeout)

    logger.info('Creating metronome client with: %r', metronome_url)
    return Client(rpc_client)
Example #34
0
def _show(name):
    """
    :returns: process status
    :rtype: int
    """

    toml_config = config.get_config(True)

    if name is not None:
        file_value = toml_config.get(name)
        try:
            # If the user presented a partial key name, eg 'core' when
            # we have 'core.xyz'; we will get an exception here
            effective_value, envvar_name = config.get_config_val_envvar(name)
        except DCOSException as e:
            # The expected case of a partial key name has special
            # handling via this mechanism.
            if isinstance(file_value, collections.Mapping):
                exc_msg = config.generate_choice_msg(name, file_value)
                raise DCOSException(exc_msg)
            raise  # Unexpected errors, pass right along

        if effective_value is None:
            raise DCOSException("Property {!r} doesn't exist".format(name))
        else:
            msg = _format_config(file_value,
                                 effective_value,
                                 envvar_name=envvar_name)
            emitter.publish(msg)

    else:
        # Let's list all of the values
        for key, value in sorted(toml_config.property_items()):
            file_value = toml_config.get(key)
            effective_value, envvar_name = config.get_config_val_envvar(key)

            msg = _format_config(file_value,
                                 effective_value,
                                 key,
                                 envvar_name=envvar_name)
            emitter.publish(msg)

    return 0
Example #35
0
def _get_metronome_url(toml_config=None):
    """
    :param toml_config: configuration dictionary
    :type toml_config: config.Toml
    :returns: metronome base url
    :rtype: str
    """
    if toml_config is None:
        toml_config = config.get_config()

    metronome_url = config.get_config_val('metronome.url', toml_config)
    if metronome_url is None:
        # dcos must be capable to use dcos_url
        _check_capability()
        dcos_url = config.get_config_val('core.dcos_url', toml_config)
        if dcos_url is None:
            raise config.missing_config_exception(['core.dcos_url'])
        metronome_url = urllib.parse.urljoin(dcos_url, 'service/metronome/')

    return metronome_url
Example #36
0
def _get_metronome_url(toml_config=None):
    """
    :param toml_config: configuration dictionary
    :type toml_config: config.Toml
    :returns: metronome base url
    :rtype: str
    """
    if toml_config is None:
        toml_config = config.get_config()

    metronome_url = config.get_config_val('metronome.url', toml_config)
    if metronome_url is None:
        # dcos must be capable to use dcos_url
        _check_capability()
        dcos_url = config.get_config_val('core.dcos_url', toml_config)
        if dcos_url is None:
            raise config.missing_config_exception(['core.dcos_url'])
        metronome_url = urllib.parse.urljoin(dcos_url, 'service/metronome/')

    return metronome_url
Example #37
0
def _show(name):
    """
    :returns: process status
    :rtype: int
    """

    toml_config = config.get_config(True)

    if name is not None:
        file_value = toml_config.get(name)
        try:
            # If the user presented a partial key name, eg 'core' when
            # we have 'core.xyz'; we will get an exception here
            effective_value, envvar_name = config.get_config_val_envvar(name)
        except DCOSException as e:
            # The expected case of a partial key name has special
            # handling via this mechanism.
            if isinstance(file_value, collections.Mapping):
                exc_msg = config.generate_choice_msg(name, file_value)
                raise DCOSException(exc_msg)
            raise  # Unexpected errors, pass right along

        if effective_value is None:
            raise DCOSException("Property {!r} doesn't exist".format(name))
        else:
            msg = _format_config(file_value, effective_value,
                                 envvar_name=envvar_name)
            emitter.publish(msg)

    else:
        # Let's list all of the values
        for key, value in sorted(toml_config.property_items()):
            file_value = toml_config.get(key)
            effective_value, envvar_name = config.get_config_val_envvar(key)

            msg = _format_config(file_value, effective_value, key,
                                 envvar_name=envvar_name)
            emitter.publish(msg)

    return 0
Example #38
0
def update_config(name, value, env=None):
    """ Context manager for altering config for tests

    :param key: <key>
    :type key: str
    :param value: <value>
    :type value: str
    ;param env: env vars
    :type env: dict
    :rtype: None
    """

    toml_config = config.get_config(True)

    result = toml_config.get(name)

    # when we change the dcos_url we remove the acs_token
    # we need to also restore the token if this occurs
    token = None
    if name == "core.dcos_url":
        token = toml_config.get("core.dcos_acs_token")

    # if we are setting a value
    if value is not None:
        config_set(name, value, env)
    # only unset if the config param already exists
    elif result is not None:
        config_unset(name, env)

    try:
        yield
    finally:
        # return config to previous state
        if result is not None:
            config_set(name, str(result), env)
        else:
            exec_command(['dcos', 'config', 'unset', name], env)

    if token:
        config_set("core.dcos_acs_token", token, env)
Example #39
0
def _verify_ssl(verify=None, toml_config=None):
    """Returns whether to verify ssl

    :param verify: whether to verify SSL certs or path to cert(s)
    :type verify: bool | str
    :param toml_config: cluster config to use
    :type toml_config: Toml
    :return: whether to verify SSL certs or path to cert(s)
    :rtype: bool | str
    """

    if toml_config is None:
        toml_config = config.get_config()

    if verify is None:
        verify = config.get_config_val("core.ssl_verify", toml_config)
        if verify and verify.lower() == "true":
            verify = True
        elif verify and verify.lower() == "false":
            verify = False

    return verify
Example #40
0
 def __init__(self, ctx):
     self._master_url = None
     self._zk_url = None
     self._marathon_url = None
     self._framework_url = None
     self.ctx = ctx
     try:
         self.ctx.vlog("Attempting to create DCOSClient")
         dcos_client = mesos.DCOSClient()
         self.client = dcos_client
         dcos_url = self.client.get_dcos_url("")
         ssl_verify = dcos_config.get_config().get("core.ssl_verify")
         self.ctx.vlog("DCOS core.ssl_verify value = " + ssl_verify)
         if ssl_verify is not None and (not ssl_verify or ssl_verify == "false"):
             self.ctx.vlog("Setting insecure_ssl to True")
             self.ctx.insecure_ssl = True
         if dcos_url is None:
             raise Exception("Unable to find DCOS server URL")
         dcos_url.rstrip("/")
         self.dcos_url = dcos_url
     except dcos_errors.DCOSException:
         raise Exception("DCOS is not configured properly")
Example #41
0
def _get_dcos_auth(auth_scheme, username, password, hostname):
    """Get authentication flow for dcos acs auth and dcos oauth

    :param auth_scheme: authentication_scheme
    :type auth_scheme: str
    :param username: username user for authentication
    :type username: str
    :param password: password for authentication
    :type password: str
    :param hostname: hostname for credentials
    :type hostname: str
    :returns: DCOSAcsAuth
    :rtype: AuthBase
    """

    toml_config = config.get_config()
    token = config.get_config_val("core.dcos_acs_token", toml_config)
    if token is None:
        dcos_url = config.get_config_val("core.dcos_url", toml_config)
        if auth_scheme == "acsjwt":
            creds = _get_dcos_acs_auth_creds(username, password, hostname)
        else:
            creds = _get_dcos_oauth_creds(dcos_url)

        verify = _verify_ssl()
        # Silence 'Unverified HTTPS request' and 'SecurityWarning' for bad cert
        if verify is not None:
            silence_requests_warnings()

        url = urllib.parse.urljoin(dcos_url, 'acs/api/v1/auth/login')
        # using private method here, so we don't retry on this request
        # error here will be bubbled up to _request_with_auth
        response = _request('post', url, json=creds, verify=verify)

        if response.status_code == 200:
            token = response.json()['token']
            config.set_val("core.dcos_acs_token", token)

    return DCOSAcsAuth(token)
Example #42
0
def _get_dcos_auth(auth_scheme, username, password, hostname):
    """Get authentication flow for dcos acs auth and dcos oauth

    :param auth_scheme: authentication_scheme
    :type auth_scheme: str
    :param username: username user for authentication
    :type username: str
    :param password: password for authentication
    :type password: str
    :param hostname: hostname for credentials
    :type hostname: str
    :returns: DCOSAcsAuth
    :rtype: AuthBase
    """

    toml_config = config.get_config()
    token = config.get_config_val("core.dcos_acs_token", toml_config)
    if token is None:
        dcos_url = config.get_config_val("core.dcos_url", toml_config)
        if auth_scheme == "acsjwt":
            creds = _get_dcos_acs_auth_creds(username, password, hostname)
        else:
            creds = _get_dcos_oauth_creds(dcos_url)

        verify = _verify_ssl()
        # Silence 'Unverified HTTPS request' and 'SecurityWarning' for bad cert
        if verify is not None:
            silence_requests_warnings()

        url = urllib.parse.urljoin(dcos_url, 'acs/api/v1/auth/login')
        # using private method here, so we don't retry on this request
        # error here will be bubbled up to _request_with_auth
        response = _request('post', url, json=creds, verify=verify)

        if response.status_code == 200:
            token = response.json()['token']
            config.set_val("core.dcos_acs_token", token)

    return DCOSAcsAuth(token)
Example #43
0
 def __init__(self, ctx):
     self._master_url = None
     self._zk_url = None
     self._marathon_url = None
     self._framework_url = None
     self.ctx = ctx
     try:
         self.ctx.vlog('Attempting to create DCOSClient')
         dcos_client = mesos.DCOSClient()
         self.client = dcos_client
         dcos_url = self.client.get_dcos_url('')
         ssl_verify = dcos_config.get_config().get('core.ssl_verify')
         self.ctx.vlog('DCOS core.ssl_verify value = ' + ssl_verify)
         if ssl_verify is not None and (not ssl_verify
                                        or ssl_verify == 'false'):
             self.ctx.vlog('Setting insecure_ssl to True')
             self.ctx.insecure_ssl = True
         if dcos_url is None:
             raise Exception("Unable to find DCOS server URL")
         dcos_url.rstrip('/')
         self.dcos_url = dcos_url
     except dcos_errors.DCOSException:
         raise Exception("DCOS is not configured properly")
Example #44
0
def _show(name):
    """
    :returns: process status
    :rtype: int
    """

    toml_config = config.get_config(True)

    if name is not None:
        value = toml_config.get(name)
        if value is None:
            raise DCOSException("Property {!r} doesn't exist".format(name))
        elif isinstance(value, collections.Mapping):
            raise DCOSException(config.generate_choice_msg(name, value))
        else:
            emitter.publish(value)
    else:
        # Let's list all of the values
        for key, value in sorted(toml_config.property_items()):
            if key == "core.dcos_acs_token":
                value = "*" * 8
            emitter.publish('{} {}'.format(key, value))

    return 0
Example #45
0
def _show(name):
    """
    :returns: process status
    :rtype: int
    """

    toml_config = config.get_config(True)

    if name is not None:
        value = toml_config.get(name)
        if value is None:
            raise DCOSException("Property {!r} doesn't exist".format(name))
        elif isinstance(value, collections.Mapping):
            raise DCOSException(config.generate_choice_msg(name, value))
        else:
            emitter.publish(value)
    else:
        # Let's list all of the values
        for key, value in sorted(toml_config.property_items()):
            if key == "core.dcos_acs_token":
                value = "*"*8
            emitter.publish('{}={}'.format(key, value))

    return 0
Example #46
0
def _cert_verification():
    try:
        core_verify_ssl = config.get_config()['core.ssl_verify']
        return str(core_verify_ssl).lower() in ['true', 'yes', '1']
    except:
        return True
Example #47
0
def get_spark_webui():
    base_url = config.get_config().get("core.dcos_url")
    return base_url + "/service/" + service.app_id() + "/ui"
Example #48
0
def _request_with_auth(response,
                       method,
                       url,
                       is_success=_default_is_success,
                       timeout=None,
                       verify=None,
                       **kwargs):
    """Try request (3 times) with credentials if 401 returned from server

    :param response: requests.response
    :type response: requests.Response
    :param method: method for the new Request object
    :type method: str
    :param url: URL for the new Request object
    :type url: str
    :param is_success: Defines successful status codes for the request
    :type is_success: Function from int to bool
    :param timeout: request timeout
    :type timeout: int
    :param verify: whether to verify SSL certs or path to cert(s)
    :type verify: bool | str
    :param kwargs: Additional arguments to requests.request
        (see http://docs.python-requests.org/en/latest/api/#requests.request)
    :type kwargs: dict
    :rtype: requests.Response
    """

    i = 0
    while i < 3 and response.status_code == 401:
        parsed_url = urlparse(url)
        hostname = parsed_url.hostname
        auth_scheme, realm = get_auth_scheme(response)
        creds = (hostname, auth_scheme, realm)

        with lock:
            if creds not in AUTH_CREDS:
                auth = _get_http_auth(response, parsed_url, auth_scheme)
            else:
                auth = AUTH_CREDS[creds]

        # try request again, with auth
        response = _request(method, url, is_success, timeout, auth,
                            verify, **kwargs)

        # only store credentials if they're valid
        with lock:
            if creds not in AUTH_CREDS and response.status_code == 200:
                AUTH_CREDS[creds] = auth
            # acs invalid token
            elif response.status_code == 401 and \
                    auth_scheme in ["acsjwt", "oauthjwt"]:

                if config.get_config().get("core.dcos_acs_token") is not None:
                    msg = ("Your core.dcos_acs_token is invalid. "
                           "Please run: `dcos auth login`")
                    raise DCOSException(msg)

        i += 1

    if response.status_code == 401:
        raise DCOSAuthenticationException(response)

    return response
Example #49
0
def app_id():
    try:
        return config.get_config()["spark.app_id"]
    except KeyError:
        return "spark"
Example #50
0
def _cert_verification():
    try:
        core_verify_ssl = config.get_config()['core.ssl_verify']
        return str(core_verify_ssl).lower() in ['true', 'yes', '1']
    except:
        return True
Example #51
0
def request(method,
            url,
            is_success=_default_is_success,
            timeout=DEFAULT_TIMEOUT,
            verify=None,
            toml_config=None,
            **kwargs):
    """Sends an HTTP request. If the server responds with a 401, ask the
    user for their credentials, and try request again (up to 3 times).

    :param method: method for the new Request object
    :type method: str
    :param url: URL for the new Request object
    :type url: str
    :param is_success: Defines successful status codes for the request
    :type is_success: Function from int to bool
    :param timeout: request timeout
    :type timeout: int
    :param verify: whether to verify SSL certs or path to cert(s)
    :type verify: bool | str
    :param toml_config: cluster config to use
    :type toml_config: Toml
    :param kwargs: Additional arguments to requests.request
        (see http://docs.python-requests.org/en/latest/api/#requests.request)
    :type kwargs: dict
    :rtype: Response
    """

    if toml_config is None:
        toml_config = config.get_config()

    auth_token = config.get_config_val("core.dcos_acs_token", toml_config)
    prompt_login = config.get_config_val("core.prompt_login", toml_config)
    dcos_url = urlparse(config.get_config_val("core.dcos_url", toml_config))

    # only request with DC/OS Auth if request is to DC/OS cluster
    if auth_token and _is_request_to_dcos(url):
        auth = DCOSAcsAuth(auth_token)
    else:
        auth = None

    response = _request(method,
                        url,
                        is_success,
                        timeout,
                        auth=auth,
                        verify=verify,
                        toml_config=toml_config,
                        **kwargs)

    if is_success(response.status_code):
        return response
    elif response.status_code == 401:
        if prompt_login:
            # I don't like having imports that aren't at the top level, but
            # this is to resolve a circular import issue between shakedown.http and
            # dcos.auth
            from dcos.auth import header_challenge_auth

            header_challenge_auth(dcos_url.geturl())
            # if header_challenge_auth succeeded, then we auth-ed correctly and
            # thus can safely recursively call ourselves and not have to worry
            # about an infinite loop
            return request(method=method,
                           url=url,
                           is_success=is_success,
                           timeout=timeout,
                           verify=verify,
                           **kwargs)
        else:
            if auth_token is not None:
                msg = ("Your core.dcos_acs_token is invalid. "
                       "Please run: `dcos auth login`")
                raise DCOSAuthenticationException(response, msg)
            else:
                raise DCOSAuthenticationException(response)
    elif response.status_code == 422:
        raise DCOSUnprocessableException(response)
    elif response.status_code == 403:
        raise DCOSAuthorizationException(response)
    elif response.status_code == 400:
        raise DCOSBadRequest(response)
    else:
        raise DCOSHTTPException(response)
Example #52
0
def _get_token():
    dcos_url = config.get_config().get('core.dcos_url')
    hostname = urllib.parse.urlparse(dcos_url).hostname
    return http._get_dcos_auth(None, None, None, hostname).token
Example #53
0
def _spark_dist_dir():
    dist_dir = config.get_config().get('spark.distribution_directory',
                                       '~/.dcos/spark/dist')
    return os.path.expanduser(dist_dir)
Example #54
0
def _request(method,
             url,
             is_success=_default_is_success,
             timeout=True,
             auth=None,
             verify=None,
             toml_config=None,
             **kwargs):
    """Sends an HTTP request.

    :param method: method for the new Request object
    :type method: str
    :param url: URL for the new Request object
    :type url: str
    :param is_success: Defines successful status codes for the request
    :type is_success: Function from int to bool
    :param timeout: How many seconds to wait for the server to send data
                    before aborting and raising an exception. A timeout is
                    either a float, a (connect timeout, read timeout) tuple
                    or `None`. `None` means unlimited timeout. If no timeout
                    is passed it defaults to the DEFAULT_TIMEOUT tuple, where
                    the connect timeout can optionally be overridden by the
                    `core.timeout` config.
    :type timeout: int | float | None | bool |
                   (int | float | None, int | float | None)
    :param auth: authentication
    :type auth: AuthBase
    :param verify: whether to verify SSL certs or path to cert(s)
    :type verify: bool | str
    :param toml_config: cluster config to use
    :type toml_config: Toml
    :param kwargs: Additional arguments to requests.request
        (see http://docs.python-requests.org/en/latest/api/#requests.request)
    :type kwargs: dict
    :rtype: Response
    """

    if timeout is True:
        if toml_config is None:
            toml_config = config.get_config()

        timeout = config.get_config_val("core.timeout", toml_config)
        timeout = (DEFAULT_CONNECT_TIMEOUT, timeout or DEFAULT_READ_TIMEOUT)
    elif type(timeout) in (float, int):
        timeout = (DEFAULT_CONNECT_TIMEOUT, timeout)

    if 'headers' not in kwargs:
        kwargs['headers'] = {'Accept': 'application/json'}

    verify = _verify_ssl(url, verify, toml_config)

    # Silence 'Unverified HTTPS request' and 'SecurityWarning' for bad certs
    if verify is not None:
        silence_requests_warnings()

    logger.info('Sending HTTP [%r] to [%r]: %r', method, url,
                kwargs.get('headers'))

    try:
        response = requests.request(method=method,
                                    url=url,
                                    timeout=timeout,
                                    auth=auth,
                                    verify=verify,
                                    **kwargs)
    except requests.exceptions.SSLError as e:
        logger.exception("HTTP SSL Error")
        msg = ("An SSL error occurred. To configure your SSL settings, "
               "please run: `dcos config set core.ssl_verify <value>`")
        description = config.get_property_description("core", "ssl_verify")
        if description is not None:
            msg += "\n<value>: {}".format(description)
        raise DCOSException(msg)
    except requests.exceptions.ConnectionError as e:
        logger.exception("HTTP Connection Error")
        raise DCOSConnectionError(url)
    except requests.exceptions.Timeout as e:
        logger.exception("HTTP Timeout")
        raise DCOSException('Request to URL [{0}] timed out.'.format(url))
    except requests.exceptions.RequestException as e:
        logger.exception("HTTP Exception")
        raise DCOSException('HTTP Exception: {}'.format(e))

    logger.info('Received HTTP response [%r]: %r', response.status_code,
                response.headers)

    return response
Example #55
0
def _get_token():
    dcos_url = config.get_config().get('core.dcos_url')
    hostname = urllib.parse.urlparse(dcos_url).hostname
    return http._get_dcos_auth(None, None, None, hostname).token
Example #56
0
def _spark_dist_dir():
    dist_dir = config.get_config().get('spark.distribution_directory',
                                       '~/.dcos/spark/dist')
    return os.path.expanduser(dist_dir)