Merge pull request #276 from mesosphere/remove-ssh-agent
remove ssh-agent from `dcos node ssh`
This commit is contained in:
@@ -23,7 +23,6 @@ Options:
|
||||
--version Show version
|
||||
"""
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
import dcoscli
|
||||
@@ -186,15 +185,7 @@ def _ssh(master, slave, option, config_file, user):
|
||||
:returns: process return code
|
||||
|
||||
"""
|
||||
if not os.environ.get('SSH_AUTH_SOCK'):
|
||||
raise DCOSException(
|
||||
"There is no SSH_AUTH_SOCK env variable, which likely means you " +
|
||||
"aren't running `ssh-agent`. `dcos node ssh` depends on " +
|
||||
"`ssh-agent` so we can safely use your private key to hop " +
|
||||
"between nodes in your cluster. Please run `ssh-agent`, " +
|
||||
"then add your private key with `ssh-add`.")
|
||||
|
||||
master_public_ip = mesos.DCOSClient().metadata()['PUBLIC_IPV4']
|
||||
ssh_options = ' '.join('-o {}'.format(opt) for opt in option)
|
||||
|
||||
if config_file:
|
||||
@@ -203,7 +194,7 @@ def _ssh(master, slave, option, config_file, user):
|
||||
ssh_config = ''
|
||||
|
||||
if master:
|
||||
host = 'leader.mesos'
|
||||
host = mesos.MesosDNSClient().hosts('leader.mesos.')[0]['ip']
|
||||
else:
|
||||
summary = mesos.DCOSClient().get_state_summary()
|
||||
slave_obj = next((slave_ for slave_ in summary['slaves']
|
||||
@@ -214,11 +205,10 @@ def _ssh(master, slave, option, config_file, user):
|
||||
else:
|
||||
raise DCOSException('No slave found with ID [{}]'.format(slave))
|
||||
|
||||
cmd = "ssh -A -t {0} {1} {2}@{3} ssh -A -t {2}@{4}".format(
|
||||
cmd = "ssh -t {0} {1} {2}@{3}".format(
|
||||
ssh_options,
|
||||
ssh_config,
|
||||
user,
|
||||
master_public_ip,
|
||||
host)
|
||||
|
||||
return subprocess.call(cmd, shell=True)
|
||||
|
||||
@@ -145,26 +145,14 @@ def test_node_ssh_user():
|
||||
assert stderr.startswith(b'Permission denied')
|
||||
|
||||
|
||||
def test_node_ssh_no_agent():
|
||||
stderr = (b"There is no SSH_AUTH_SOCK env variable, which likely means "
|
||||
b"you aren't running `ssh-agent`. `dcos node ssh` depends on"
|
||||
b" `ssh-agent` so we can safely use your private key to hop "
|
||||
b"between nodes in your cluster. Please run `ssh-agent`, then "
|
||||
b"add your private key with `ssh-add`.\n")
|
||||
assert_command(['dcos', 'node', 'ssh', '--master'],
|
||||
stdout=b'',
|
||||
stderr=stderr,
|
||||
returncode=1)
|
||||
|
||||
|
||||
def _node_ssh_output(args):
|
||||
# ssh must run with stdin attached to a tty
|
||||
master, slave = pty.openpty()
|
||||
cmd = ('dcos node ssh --option ' +
|
||||
'IdentityFile=/host-home/.vagrant.d/insecure_private_key ' +
|
||||
'--option StrictHostKeyChecking=no ' +
|
||||
'{}').format(' '.join(args))
|
||||
|
||||
cmd = ('ssh-agent /bin/bash -c ' +
|
||||
'"ssh-add /host-home/.vagrant.d/insecure_private_key ' +
|
||||
'2> /dev/null && dcos node ssh --option StrictHostKeyChecking=no' +
|
||||
' {}"').format(' '.join(args))
|
||||
proc = subprocess.Popen(cmd,
|
||||
stdin=slave,
|
||||
stdout=subprocess.PIPE,
|
||||
|
||||
29
dcos/http.py
29
dcos/http.py
@@ -66,22 +66,21 @@ def request(method,
|
||||
:rtype: Response
|
||||
"""
|
||||
|
||||
if 'headers' not in kwargs:
|
||||
kwargs['headers'] = {'Accept': 'application/json'}
|
||||
|
||||
request = requests.Request(
|
||||
method=method,
|
||||
url=url,
|
||||
**kwargs)
|
||||
|
||||
logger.info(
|
||||
'Sending HTTP [%r] to [%r]: %r',
|
||||
request.method,
|
||||
request.url,
|
||||
request.headers)
|
||||
|
||||
try:
|
||||
if 'headers' in kwargs:
|
||||
request = requests.Request(method=method, url=url, **kwargs)
|
||||
else:
|
||||
request = requests.Request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers={'Accept': 'application/json'},
|
||||
**kwargs)
|
||||
|
||||
logger.info(
|
||||
'Sending HTTP [%r] to [%r]: %r',
|
||||
request.method,
|
||||
request.url,
|
||||
request.headers)
|
||||
|
||||
with requests.Session() as session:
|
||||
response = session.send(request.prepare(), timeout=timeout,
|
||||
proxies=util.get_proxy_dict_from_env())
|
||||
|
||||
@@ -37,7 +37,7 @@ def _get_marathon_url(config):
|
||||
|
||||
marathon_url = config.get('marathon.url')
|
||||
if marathon_url is None:
|
||||
dcos_url = util.get_config_vals(config, ['core.dcos_url'])[0]
|
||||
dcos_url = util.get_config_vals(['core.dcos_url'], config)[0]
|
||||
marathon_url = urllib.parse.urljoin(dcos_url, 'marathon/')
|
||||
|
||||
return marathon_url
|
||||
|
||||
@@ -36,7 +36,7 @@ class DCOSClient(object):
|
||||
|
||||
mesos_master_url = config.get('core.mesos_master_url')
|
||||
if mesos_master_url is None:
|
||||
self._dcos_url = util.get_config_vals(config, ['core.dcos_url'])[0]
|
||||
self._dcos_url = util.get_config_vals(['core.dcos_url'], config)[0]
|
||||
else:
|
||||
self._mesos_master_url = mesos_master_url
|
||||
|
||||
@@ -203,6 +203,38 @@ class DCOSClient(object):
|
||||
return http.get(url).json()
|
||||
|
||||
|
||||
class MesosDNSClient(object):
|
||||
""" Mesos-DNS client
|
||||
|
||||
:param url: mesos-dns URL
|
||||
:type url: str
|
||||
"""
|
||||
def __init__(self, url=None):
|
||||
self.url = url or urllib.parse.urljoin(
|
||||
util.get_config_vals(['core.dcos_url'])[0], '/mesos_dns/')
|
||||
|
||||
def _path(self, path):
|
||||
""" Construct a full path
|
||||
|
||||
:param path: path suffix
|
||||
:type path: str
|
||||
:returns: full path
|
||||
:rtype: str
|
||||
"""
|
||||
return urllib.parse.urljoin(self.url, path)
|
||||
|
||||
def hosts(self, host):
|
||||
""" GET v1/hosts/<host>
|
||||
|
||||
:param host: host
|
||||
:type host: str
|
||||
:returns: {'ip', 'host'} dictionary
|
||||
:rtype: dict(str, str)
|
||||
"""
|
||||
url = self._path('v1/hosts/{}'.format(host))
|
||||
return http.get(url, headers={}).json()
|
||||
|
||||
|
||||
class Master(object):
|
||||
"""Mesos Master Model
|
||||
|
||||
|
||||
@@ -590,7 +590,7 @@ def list_sources(config):
|
||||
:rtype: [Source]
|
||||
"""
|
||||
|
||||
source_uris = util.get_config_vals(config, ['package.sources'])[0]
|
||||
source_uris = util.get_config_vals(['package.sources'], config)[0]
|
||||
|
||||
sources = [url_to_source(s) for s in source_uris]
|
||||
|
||||
@@ -659,7 +659,7 @@ def update_sources(config, validate=False):
|
||||
|
||||
# ensure the cache directory is properly configured
|
||||
cache_dir = os.path.expanduser(
|
||||
util.get_config_vals(config, ['package.cache'])[0])
|
||||
util.get_config_vals(['package.cache'], config)[0])
|
||||
|
||||
# ensure the cache directory exists
|
||||
if not os.path.exists(cache_dir):
|
||||
@@ -758,7 +758,7 @@ class Source:
|
||||
"""
|
||||
|
||||
cache_dir = os.path.expanduser(
|
||||
util.get_config_vals(config, ['package.cache'])[0])
|
||||
util.get_config_vals(['package.cache'], config)[0])
|
||||
return os.path.join(cache_dir, self.hash())
|
||||
|
||||
def copy_to_cache(self, target_dir):
|
||||
|
||||
@@ -115,7 +115,7 @@ def get_config():
|
||||
os.environ[constants.DCOS_CONFIG_ENV])
|
||||
|
||||
|
||||
def get_config_vals(config, keys):
|
||||
def get_config_vals(keys, config=None):
|
||||
"""Gets config values for each of the keys. Raises a DCOSException if
|
||||
any of the keys don't exist.
|
||||
|
||||
@@ -127,6 +127,7 @@ def get_config_vals(config, keys):
|
||||
:rtype: [object]
|
||||
"""
|
||||
|
||||
config = config or get_config()
|
||||
missing = [key for key in keys if key not in config]
|
||||
if missing:
|
||||
raise missing_config_exception(keys)
|
||||
|
||||
Reference in New Issue
Block a user