From e3696d56034510f58d7ca659463768a78c626ac8 Mon Sep 17 00:00:00 2001 From: Joseph Hall Date: Mon, 22 Feb 2016 16:02:05 -0700 Subject: [PATCH 1/3] Add some auth handling for etcd --- salt/returners/etcd_return.py | 52 +++++++++++++++++++++++++++++++---- salt/utils/etcd_util.py | 15 +++++++++- 2 files changed, 60 insertions(+), 7 deletions(-) diff --git a/salt/returners/etcd_return.py b/salt/returners/etcd_return.py index 6eba2c9d21..7fffd3e971 100644 --- a/salt/returners/etcd_return.py +++ b/salt/returners/etcd_return.py @@ -39,6 +39,30 @@ Once the etcd options are configured, the returner may be used: CLI Example: salt '*' test.ping --return etcd + +A username and password can be set: + +.. code-block:: yaml + + etcd.username: larry # Optional; requires etcd.password to be set + etcd.password: 123pass # Optional; requires etcd.username to be set + +You can also set a TTL (time to live) value for the returner: + +.. code-block:: yaml + + etcd.ttl: 5 + +Authentication with username and password, and ttl, currently requires the +``master`` branch of ``python-etcd``. + +You may also specify different roles for read and write operations. First, +create the profiles as specified above. Then add: + +.. code-block:: yaml + + etcd.returner_read_profile: my_etcd_read + etcd.returner_write_profile: my_etcd_write ''' from __future__ import absolute_import @@ -69,11 +93,12 @@ def __virtual__(): return __virtualname__ if HAS_LIBS else False -def _get_conn(opts): +def _get_conn(opts, profile=None): ''' Establish a connection to etcd ''' - profile = opts.get('etcd.returner', None) + if profile is None: + profile = opts.get('etcd.returner', None) path = opts.get('etcd.returner_root', '/salt/return') return salt.utils.etcd_util.get_conn(opts, profile), path @@ -82,12 +107,18 @@ def returner(ret): ''' Return data to an etcd server or cluster ''' - client, path = _get_conn(__opts__) + write_profile = __opts__.get('etcd.returner_write_profile', None) + if write_profile: + ttl = __opts__.get(write_profile, {}).get('etcd.ttl') + else: + ttl = __opts__.get('etcd.ttl') + client, path = _get_conn(__opts__, write_profile) # Make a note of this minion for the external job cache client.set( '/'.join((path, 'minions', ret['id'])), ret['jid'], + ttl=ttl, ) for field in ret: @@ -99,7 +130,7 @@ def returner(ret): ret['id'], field )) - client.set(dest, json.dumps(ret[field])) + client.set(dest, json.dumps(ret[field]), ttl=ttl) def save_load(jid, load): @@ -107,9 +138,17 @@ def save_load(jid, load): Save the load to the specified jid ''' client, path = _get_conn(__opts__) + client.set( + write_profile = __opts__.get('etcd.returner_write_profile', None) + client, path = _get_conn(__opts__, write_profile) + if write_profile: + ttl = __opts__.get(write_profile, {}).get('etcd.ttl') + else: + ttl = __opts__.get('etcd.ttl') client.set( '/'.join((path, 'jobs', jid, '.load.p')), - json.dumps(load) + json.dumps(load), + ttl=ttl, ) @@ -117,7 +156,8 @@ def get_load(jid): ''' Return the load data that marks a specified jid ''' - client, path = _get_conn(__opts__) + read_profile = __opts__.get('etcd.returner_read_profile', None) + client, path = _get_conn(__opts__, read_profile) return json.loads(client.get('/'.join((path, 'jobs', jid, '.load.p')))) diff --git a/salt/utils/etcd_util.py b/salt/utils/etcd_util.py index 6eeaba1de3..0c30047009 100644 --- a/salt/utils/etcd_util.py +++ b/salt/utils/etcd_util.py @@ -15,11 +15,15 @@ may be passed in. The following configurations are both valid: # No profile name etcd.host: 127.0.0.1 etcd.port: 4001 + etcd.username: larry # Optional; requires etcd.password to be set + etcd.password: 123pass # Optional; requires etcd.username to be set # One or more profiles defined my_etcd_config: etcd.host: 127.0.0.1 etcd.port: 4001 + etcd.username: larry # Optional; requires etcd.password to be set + etcd.password: 123pass # Optional; requires etcd.username to be set Once configured, the client() function is passed a set of opts, and optionally, the name of a profile to be used. @@ -84,9 +88,18 @@ class EtcdClient(object): host = self.conf.get('etcd.host', '127.0.0.1') port = self.conf.get('etcd.port', 4001) + username = self.conf.get('etcd.username') + password = self.conf.get('etcd.password') + + auth = {} + if username and password: + auth = { + 'username': str(username), + 'password': str(password) + } if HAS_LIBS: - self.client = etcd.Client(host, port) + self.client = etcd.Client(host, port, **auth) else: raise CommandExecutionError( '(unable to import etcd, ' From a7c87963818fb55999ea6dc8abfbb90fdf118160 Mon Sep 17 00:00:00 2001 From: Joseph Hall Date: Mon, 22 Feb 2016 16:16:05 -0700 Subject: [PATCH 2/3] Removing redundant Nones --- salt/returners/etcd_return.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/salt/returners/etcd_return.py b/salt/returners/etcd_return.py index 7fffd3e971..8348aa11e5 100644 --- a/salt/returners/etcd_return.py +++ b/salt/returners/etcd_return.py @@ -98,7 +98,7 @@ def _get_conn(opts, profile=None): Establish a connection to etcd ''' if profile is None: - profile = opts.get('etcd.returner', None) + profile = opts.get('etcd.returner') path = opts.get('etcd.returner_root', '/salt/return') return salt.utils.etcd_util.get_conn(opts, profile), path @@ -107,7 +107,7 @@ def returner(ret): ''' Return data to an etcd server or cluster ''' - write_profile = __opts__.get('etcd.returner_write_profile', None) + write_profile = __opts__.get('etcd.returner_write_profile') if write_profile: ttl = __opts__.get(write_profile, {}).get('etcd.ttl') else: @@ -139,7 +139,7 @@ def save_load(jid, load): ''' client, path = _get_conn(__opts__) client.set( - write_profile = __opts__.get('etcd.returner_write_profile', None) + write_profile = __opts__.get('etcd.returner_write_profile') client, path = _get_conn(__opts__, write_profile) if write_profile: ttl = __opts__.get(write_profile, {}).get('etcd.ttl') @@ -156,7 +156,7 @@ def get_load(jid): ''' Return the load data that marks a specified jid ''' - read_profile = __opts__.get('etcd.returner_read_profile', None) + read_profile = __opts__.get('etcd.returner_read_profile') client, path = _get_conn(__opts__, read_profile) return json.loads(client.get('/'.join((path, 'jobs', jid, '.load.p')))) From 5301f4239b361178bbe5bffab9686bcfd8cbf768 Mon Sep 17 00:00:00 2001 From: Joseph Hall Date: Mon, 22 Feb 2016 16:36:23 -0700 Subject: [PATCH 3/3] Fixing syntax error --- salt/returners/etcd_return.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/salt/returners/etcd_return.py b/salt/returners/etcd_return.py index 8348aa11e5..90a6d645fe 100644 --- a/salt/returners/etcd_return.py +++ b/salt/returners/etcd_return.py @@ -137,8 +137,6 @@ def save_load(jid, load): ''' Save the load to the specified jid ''' - client, path = _get_conn(__opts__) - client.set( write_profile = __opts__.get('etcd.returner_write_profile') client, path = _get_conn(__opts__, write_profile) if write_profile: