mirror of
https://github.com/valitydev/salt.git
synced 2024-11-08 09:23:56 +00:00
Merge remote-tracking branch 'upstream/develop' into unify-api
This commit is contained in:
commit
a841b5f452
@ -167,16 +167,20 @@
|
|||||||
# - cmd
|
# - cmd
|
||||||
|
|
||||||
# The external auth system uses the Salt auth modules to authenticate and
|
# The external auth system uses the Salt auth modules to authenticate and
|
||||||
# validate users to access areas of the Salt system
|
# validate users to access areas of the Salt system.
|
||||||
#
|
#
|
||||||
# external_auth:
|
# external_auth:
|
||||||
# pam:
|
# pam:
|
||||||
# fred:
|
# fred:
|
||||||
# - test.*
|
# - test.*
|
||||||
#
|
#
|
||||||
|
|
||||||
# Time (in seconds) for a newly generated token to live. Default: 12 hours
|
# Time (in seconds) for a newly generated token to live. Default: 12 hours
|
||||||
# token_expire: 43200
|
# token_expire: 43200
|
||||||
|
|
||||||
|
# Allow minions to push files to the master. This is disabled by default, for
|
||||||
|
# security purposes.
|
||||||
|
# file_recv: False
|
||||||
|
|
||||||
##### Master Module Management #####
|
##### Master Module Management #####
|
||||||
##########################################
|
##########################################
|
||||||
|
@ -11941,7 +11941,7 @@ salt \(aq*\(aq cp.is_cached salt://path/to/file
|
|||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
.B salt.modules.cp.list_master(env=\(aqbase\(aq)
|
.B salt.modules.cp.list_master(env=\(aqbase\(aq, prefix=\(aq\(aq)
|
||||||
List all of the files stored on the master
|
List all of the files stored on the master
|
||||||
.sp
|
.sp
|
||||||
CLI Example:
|
CLI Example:
|
||||||
@ -11954,7 +11954,7 @@ salt \(aq*\(aq cp.list_master
|
|||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
.B salt.modules.cp.list_master_dirs(env=\(aqbase\(aq)
|
.B salt.modules.cp.list_master_dirs(env=\(aqbase\(aq, prefix=\(aq\(aq)
|
||||||
List all of the directories stored on the master
|
List all of the directories stored on the master
|
||||||
.sp
|
.sp
|
||||||
CLI Example:
|
CLI Example:
|
||||||
|
@ -305,7 +305,7 @@ insecure!
|
|||||||
``client_acl``
|
``client_acl``
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
Default: {}
|
Default: ``{}``
|
||||||
|
|
||||||
Enable user accounts on the master to execute specific modules. These modules
|
Enable user accounts on the master to execute specific modules. These modules
|
||||||
can be expressed as regular expressions
|
can be expressed as regular expressions
|
||||||
@ -317,6 +317,74 @@ can be expressed as regular expressions
|
|||||||
- test.ping
|
- test.ping
|
||||||
- pkg.*
|
- pkg.*
|
||||||
|
|
||||||
|
.. conf_master:: client_acl_blacklist
|
||||||
|
|
||||||
|
``client_acl_blacklist``
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
Default: ``{}``
|
||||||
|
|
||||||
|
Blacklist users or modules
|
||||||
|
|
||||||
|
This example would blacklist all non sudo users, including root from
|
||||||
|
running any commands. It would also blacklist any use of the "cmd"
|
||||||
|
module.
|
||||||
|
|
||||||
|
This is completely disabled by default.
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
client_acl_blacklist:
|
||||||
|
users:
|
||||||
|
- root
|
||||||
|
- '^(?!sudo_).*$' # all non sudo users
|
||||||
|
modules:
|
||||||
|
- cmd
|
||||||
|
|
||||||
|
.. conf_master:: external_auth
|
||||||
|
|
||||||
|
``external_auth``
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Default: ``{}``
|
||||||
|
|
||||||
|
The external auth system uses the Salt auth modules to authenticate and
|
||||||
|
validate users to access areas of the Salt system.
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
external_auth:
|
||||||
|
pam:
|
||||||
|
fred:
|
||||||
|
- test.*
|
||||||
|
|
||||||
|
.. conf_master:: token_expire
|
||||||
|
|
||||||
|
``token_expire``
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Default: ``43200``
|
||||||
|
|
||||||
|
Time (in seconds) for a newly generated token to live. Default: 12 hours
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
token_expire: 43200
|
||||||
|
|
||||||
|
.. conf_master:: file_recv
|
||||||
|
|
||||||
|
``file_recv``
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Default: ``False``
|
||||||
|
|
||||||
|
Allow minions to push files to the master. This is disabled by default, for
|
||||||
|
security purposes.
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
file_recv: False
|
||||||
|
|
||||||
|
|
||||||
Master Module Management
|
Master Module Management
|
||||||
------------------------
|
------------------------
|
||||||
|
@ -110,3 +110,9 @@ To execute the manage.up runner:
|
|||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
# salt-call publish.runner manage.up
|
# salt-call publish.runner manage.up
|
||||||
|
|
||||||
|
To match minions using other matchers, use ``expr_form``:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
# salt-call publish.publish 'webserv* and not G@os:Ubuntu' test.ping expr_form='compound'
|
||||||
|
@ -204,3 +204,16 @@ class Resolver(object):
|
|||||||
except (IOError, OSError):
|
except (IOError, OSError):
|
||||||
pass
|
pass
|
||||||
return tdata
|
return tdata
|
||||||
|
|
||||||
|
def request_token(self, load):
|
||||||
|
'''
|
||||||
|
Request a token fromt he master
|
||||||
|
'''
|
||||||
|
load['cmd'] = 'mk_token'
|
||||||
|
sreq = salt.payload.SREQ(
|
||||||
|
'tcp://{0[interface]}:{0[ret_port]}'.format(self.opts),
|
||||||
|
)
|
||||||
|
tdata = sreq.send('clear', load)
|
||||||
|
if 'token' not in tdata:
|
||||||
|
return tdata
|
||||||
|
return tdata
|
||||||
|
@ -129,6 +129,7 @@ VALID_OPTS = {
|
|||||||
'client_acl_blacklist': dict,
|
'client_acl_blacklist': dict,
|
||||||
'external_auth': dict,
|
'external_auth': dict,
|
||||||
'token_expire': int,
|
'token_expire': int,
|
||||||
|
'file_recv': bool,
|
||||||
'file_ignore_regex': bool,
|
'file_ignore_regex': bool,
|
||||||
'file_ignore_glob': bool,
|
'file_ignore_glob': bool,
|
||||||
'fileserver_backend': list,
|
'fileserver_backend': list,
|
||||||
@ -271,6 +272,7 @@ DEFAULT_MASTER_OPTS = {
|
|||||||
'client_acl_blacklist': {},
|
'client_acl_blacklist': {},
|
||||||
'external_auth': {},
|
'external_auth': {},
|
||||||
'token_expire': 43200,
|
'token_expire': 43200,
|
||||||
|
'file_recv': False,
|
||||||
'file_buffer_size': 1048576,
|
'file_buffer_size': 1048576,
|
||||||
'file_ignore_regex': None,
|
'file_ignore_regex': None,
|
||||||
'file_ignore_glob': None,
|
'file_ignore_glob': None,
|
||||||
|
@ -102,7 +102,7 @@ class Client(object):
|
|||||||
'''
|
'''
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def file_list_emptydirs(self, env='base'):
|
def file_list_emptydirs(self, env='base', prefix=''):
|
||||||
'''
|
'''
|
||||||
List the empty dirs
|
List the empty dirs
|
||||||
'''
|
'''
|
||||||
@ -207,13 +207,13 @@ class Client(object):
|
|||||||
ldest = self._file_local_list(localfilesdest)
|
ldest = self._file_local_list(localfilesdest)
|
||||||
return sorted(fdest.union(ldest))
|
return sorted(fdest.union(ldest))
|
||||||
|
|
||||||
def file_list(self, env='base'):
|
def file_list(self, env='base', prefix=''):
|
||||||
'''
|
'''
|
||||||
This function must be overwritten
|
This function must be overwritten
|
||||||
'''
|
'''
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def dir_list(self, env='base'):
|
def dir_list(self, env='base', prefix=''):
|
||||||
'''
|
'''
|
||||||
This function must be overwritten
|
This function must be overwritten
|
||||||
'''
|
'''
|
||||||
@ -461,47 +461,56 @@ class LocalClient(Client):
|
|||||||
return ''
|
return ''
|
||||||
return fnd['path']
|
return fnd['path']
|
||||||
|
|
||||||
def file_list(self, env='base'):
|
def file_list(self, env='base', prefix=''):
|
||||||
'''
|
'''
|
||||||
Return a list of files in the given environment
|
Return a list of files in the given environment
|
||||||
|
with optional relative prefix path to limit directory traversal
|
||||||
'''
|
'''
|
||||||
ret = []
|
ret = []
|
||||||
if env not in self.opts['file_roots']:
|
if env not in self.opts['file_roots']:
|
||||||
return ret
|
return ret
|
||||||
for path in self.opts['file_roots'][env]:
|
for path in self.opts['file_roots'][env]:
|
||||||
|
if prefix:
|
||||||
|
path = os.path.join(path, prefix)
|
||||||
for root, dirs, files in os.walk(path, followlinks=True):
|
for root, dirs, files in os.walk(path, followlinks=True):
|
||||||
for fname in files:
|
for fname in files:
|
||||||
ret.append(
|
ret.append(
|
||||||
os.path.relpath(
|
os.path.relpath(
|
||||||
os.path.join(root, fname),
|
os.path.join(root, prefix, fname),
|
||||||
path
|
path
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def file_list_emptydirs(self, env='base'):
|
def file_list_emptydirs(self, env='base', prefix=''):
|
||||||
'''
|
'''
|
||||||
List the empty dirs in the file_roots
|
List the empty dirs in the file_roots
|
||||||
|
with optional relative prefix path to limit directory traversal
|
||||||
'''
|
'''
|
||||||
ret = []
|
ret = []
|
||||||
if env not in self.opts['file_roots']:
|
if env not in self.opts['file_roots']:
|
||||||
return ret
|
return ret
|
||||||
for path in self.opts['file_roots'][env]:
|
for path in self.opts['file_roots'][env]:
|
||||||
|
if prefix:
|
||||||
|
path = os.path.join(path, prefix)
|
||||||
for root, dirs, files in os.walk(path, followlinks=True):
|
for root, dirs, files in os.walk(path, followlinks=True):
|
||||||
if len(dirs) == 0 and len(files) == 0:
|
if len(dirs) == 0 and len(files) == 0:
|
||||||
ret.append(os.path.relpath(root, path))
|
ret.append(os.path.relpath(root, os.path.join(prefix, path)))
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def dir_list(self, env='base'):
|
def dir_list(self, env='base', prefix=''):
|
||||||
'''
|
'''
|
||||||
List the dirs in the file_roots
|
List the dirs in the file_roots
|
||||||
|
with optional relative prefix path to limit directory traversal
|
||||||
'''
|
'''
|
||||||
ret = []
|
ret = []
|
||||||
if env not in self.opts['file_roots']:
|
if env not in self.opts['file_roots']:
|
||||||
return ret
|
return ret
|
||||||
for path in self.opts['file_roots'][env]:
|
for path in self.opts['file_roots'][env]:
|
||||||
|
if prefix:
|
||||||
|
path = os.path.join(path, prefix)
|
||||||
for root, dirs, files in os.walk(path, followlinks=True):
|
for root, dirs, files in os.walk(path, followlinks=True):
|
||||||
ret.append(os.path.relpath(root, path))
|
ret.append(os.path.relpath(root, os.path.join(prefix, path)))
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def hash_file(self, path, env='base'):
|
def hash_file(self, path, env='base'):
|
||||||
@ -667,11 +676,12 @@ class RemoteClient(Client):
|
|||||||
fn_.close()
|
fn_.close()
|
||||||
return dest
|
return dest
|
||||||
|
|
||||||
def file_list(self, env='base'):
|
def file_list(self, env='base', prefix=''):
|
||||||
'''
|
'''
|
||||||
List the files on the master
|
List the files on the master
|
||||||
'''
|
'''
|
||||||
load = {'env': env,
|
load = {'env': env,
|
||||||
|
'prefix': prefix,
|
||||||
'cmd': '_file_list'}
|
'cmd': '_file_list'}
|
||||||
try:
|
try:
|
||||||
return self.auth.crypticle.loads(
|
return self.auth.crypticle.loads(
|
||||||
@ -683,11 +693,12 @@ class RemoteClient(Client):
|
|||||||
except SaltReqTimeoutError:
|
except SaltReqTimeoutError:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
def file_list_emptydirs(self, env='base'):
|
def file_list_emptydirs(self, env='base', prefix=''):
|
||||||
'''
|
'''
|
||||||
List the empty dirs on the master
|
List the empty dirs on the master
|
||||||
'''
|
'''
|
||||||
load = {'env': env,
|
load = {'env': env,
|
||||||
|
'prefix': prefix,
|
||||||
'cmd': '_file_list_emptydirs'}
|
'cmd': '_file_list_emptydirs'}
|
||||||
try:
|
try:
|
||||||
return self.auth.crypticle.loads(
|
return self.auth.crypticle.loads(
|
||||||
@ -699,11 +710,12 @@ class RemoteClient(Client):
|
|||||||
except SaltReqTimeoutError:
|
except SaltReqTimeoutError:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
def dir_list(self, env='base'):
|
def dir_list(self, env='base', prefix=''):
|
||||||
'''
|
'''
|
||||||
List the dirs on the master
|
List the dirs on the master
|
||||||
'''
|
'''
|
||||||
load = {'env': env,
|
load = {'env': env,
|
||||||
|
'prefix': prefix,
|
||||||
'cmd': '_dir_list'}
|
'cmd': '_dir_list'}
|
||||||
try:
|
try:
|
||||||
return self.auth.crypticle.loads(
|
return self.auth.crypticle.loads(
|
||||||
|
@ -99,10 +99,11 @@ def file_list(load):
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
for path in __opts__['file_roots'][load['env']]:
|
for path in __opts__['file_roots'][load['env']]:
|
||||||
|
path = os.path.join(path, load['prefix'])
|
||||||
for root, dirs, files in os.walk(path, followlinks=True):
|
for root, dirs, files in os.walk(path, followlinks=True):
|
||||||
for fname in files:
|
for fname in files:
|
||||||
rel_fn = os.path.relpath(
|
rel_fn = os.path.relpath(
|
||||||
os.path.join(root, fname),
|
os.path.join(root, load['prefix'], fname),
|
||||||
path
|
path
|
||||||
)
|
)
|
||||||
if not salt.fileserver.is_file_ignored(__opts__, rel_fn):
|
if not salt.fileserver.is_file_ignored(__opts__, rel_fn):
|
||||||
@ -118,11 +119,12 @@ def file_list_emptydirs(load):
|
|||||||
if load['env'] not in __opts__['file_roots']:
|
if load['env'] not in __opts__['file_roots']:
|
||||||
return ret
|
return ret
|
||||||
for path in __opts__['file_roots'][load['env']]:
|
for path in __opts__['file_roots'][load['env']]:
|
||||||
|
path = os.path.join(path, load['prefix'])
|
||||||
for root, dirs, files in os.walk(path, followlinks=True):
|
for root, dirs, files in os.walk(path, followlinks=True):
|
||||||
if len(dirs) == 0 and len(files) == 0:
|
if len(dirs) == 0 and len(files) == 0:
|
||||||
rel_fn = os.path.relpath(root, path)
|
rel_fn = os.path.relpath(root, path)
|
||||||
if not salt.fileserver.is_file_ignored(__opts__, rel_fn):
|
if not salt.fileserver.is_file_ignored(__opts__, rel_fn):
|
||||||
ret.append(rel_fn)
|
ret.append(os.path.join(load['prefix'], rel_fn))
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
@ -134,6 +136,7 @@ def dir_list(load):
|
|||||||
if load['env'] not in __opts__['file_roots']:
|
if load['env'] not in __opts__['file_roots']:
|
||||||
return ret
|
return ret
|
||||||
for path in __opts__['file_roots'][load['env']]:
|
for path in __opts__['file_roots'][load['env']]:
|
||||||
|
path = os.path.join(path, load['prefix'])
|
||||||
for root, dirs, files in os.walk(path, followlinks=True):
|
for root, dirs, files in os.walk(path, followlinks=True):
|
||||||
ret.append(os.path.relpath(root, path))
|
ret.append(os.path.relpath(root, os.path.join(load['prefix'], path)))
|
||||||
return ret
|
return ret
|
||||||
|
114
salt/master.py
114
salt/master.py
@ -743,10 +743,10 @@ class AESFuncs(object):
|
|||||||
# The minion is not who it says it is!
|
# The minion is not who it says it is!
|
||||||
# We don't want to listen to it!
|
# We don't want to listen to it!
|
||||||
log.warn(
|
log.warn(
|
||||||
('Minion id {0} is not who it says it is and is attempting '
|
(
|
||||||
'to issue a peer command').format(
|
'Minion id {0} is not who it says it is and is attempting '
|
||||||
clear_load['id']
|
'to issue a peer command'
|
||||||
)
|
).format(clear_load['id'])
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
perms = []
|
perms = []
|
||||||
@ -1324,10 +1324,10 @@ class AESFuncs(object):
|
|||||||
# The minion is not who it says it is!
|
# The minion is not who it says it is!
|
||||||
# We don't want to listen to it!
|
# We don't want to listen to it!
|
||||||
log.warn(
|
log.warn(
|
||||||
('Minion id {0} is not who it says it is and is attempting '
|
(
|
||||||
'to revoke the key for {0}').format(
|
'Minion id {0} is not who it says it is and is attempting '
|
||||||
load['id']
|
'to revoke the key for {0}'
|
||||||
)
|
).format(load['id'])
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
keyapi = salt.key.Key(self.opts)
|
keyapi = salt.key.Key(self.opts)
|
||||||
@ -1753,6 +1753,94 @@ class ClearFuncs(object):
|
|||||||
self.event.fire_event(eload, 'auth')
|
self.event.fire_event(eload, 'auth')
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
def runner(self, clear_load):
|
||||||
|
'''
|
||||||
|
Send a master control function back to the wheel system
|
||||||
|
'''
|
||||||
|
# All wheel ops pass through eauth
|
||||||
|
if 'token' in clear_load:
|
||||||
|
try:
|
||||||
|
token = self.loadauth.get_tok(clear_load['token'])
|
||||||
|
except Exception as exc:
|
||||||
|
log.error(
|
||||||
|
'Exception occurred when generating auth token: {0}'.format(
|
||||||
|
exc
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return ''
|
||||||
|
if not token:
|
||||||
|
log.warning('Authentication failure of type "token" occurred.')
|
||||||
|
return ''
|
||||||
|
if token['eauth'] not in self.opts['external_auth']:
|
||||||
|
log.warning('Authentication failure of type "token" occurred.')
|
||||||
|
return ''
|
||||||
|
if token['name'] not in self.opts['external_auth'][token['eauth']]:
|
||||||
|
log.warning('Authentication failure of type "token" occurred.')
|
||||||
|
return ''
|
||||||
|
good = self.ckminions.runner_check(
|
||||||
|
self.opts['external_auth'][clear_load['eauth']][token['name']] if token['name'] in self.opts['external_auth'][clear_load['eauth']] else self.opts['external_auth'][token['eauth']]['*'],
|
||||||
|
clear_load['fun'])
|
||||||
|
if not good:
|
||||||
|
msg = ('Authentication failure of type "eauth" occurred for '
|
||||||
|
'user {0}.').format(clear_load.get('username', 'UNKNOWN'))
|
||||||
|
log.warning(msg)
|
||||||
|
return ''
|
||||||
|
|
||||||
|
try:
|
||||||
|
fun = clear_load.pop('fun')
|
||||||
|
return self.wheel_.call_func(fun, **clear_load)
|
||||||
|
except Exception as exc:
|
||||||
|
log.error('Exception occurred while '
|
||||||
|
'introspecting {0}: {1}'.format(fun, exc))
|
||||||
|
return ''
|
||||||
|
|
||||||
|
if 'eauth' not in clear_load:
|
||||||
|
msg = ('Authentication failure of type "eauth" occurred for '
|
||||||
|
'user {0}.').format(clear_load.get('username', 'UNKNOWN'))
|
||||||
|
log.warning(msg)
|
||||||
|
return ''
|
||||||
|
if clear_load['eauth'] not in self.opts['external_auth']:
|
||||||
|
# The eauth system is not enabled, fail
|
||||||
|
msg = ('Authentication failure of type "eauth" occurred for '
|
||||||
|
'user {0}.').format(clear_load.get('username', 'UNKNOWN'))
|
||||||
|
log.warning(msg)
|
||||||
|
return ''
|
||||||
|
|
||||||
|
try:
|
||||||
|
name = self.loadauth.load_name(clear_load)
|
||||||
|
if not ((name in self.opts['external_auth'][clear_load['eauth']]) | ('*' in self.opts['external_auth'][clear_load['eauth']])):
|
||||||
|
msg = ('Authentication failure of type "eauth" occurred for '
|
||||||
|
'user {0}.').format(clear_load.get('username', 'UNKNOWN'))
|
||||||
|
log.warning(msg)
|
||||||
|
return ''
|
||||||
|
if not self.loadauth.time_auth(clear_load):
|
||||||
|
msg = ('Authentication failure of type "eauth" occurred for '
|
||||||
|
'user {0}.').format(clear_load.get('username', 'UNKNOWN'))
|
||||||
|
log.warning(msg)
|
||||||
|
return ''
|
||||||
|
good = self.ckminions.runner_check(
|
||||||
|
self.opts['external_auth'][clear_load['eauth']][name] if name in self.opts['external_auth'][clear_load['eauth']] else self.opts['external_auth'][token['eauth']]['*'],
|
||||||
|
clear_load['fun'])
|
||||||
|
if not good:
|
||||||
|
msg = ('Authentication failure of type "eauth" occurred for '
|
||||||
|
'user {0}.').format(clear_load.get('username', 'UNKNOWN'))
|
||||||
|
log.warning(msg)
|
||||||
|
return ''
|
||||||
|
|
||||||
|
try:
|
||||||
|
fun = clear_load.pop('fun')
|
||||||
|
return self.wheel_.call_func(fun, **clear_load)
|
||||||
|
except Exception as exc:
|
||||||
|
log.error('Exception occurred while '
|
||||||
|
'introspecting {0}: {1}'.format(fun, exc))
|
||||||
|
return ''
|
||||||
|
|
||||||
|
except Exception as exc:
|
||||||
|
log.error(
|
||||||
|
'Exception occurred in the wheel system: {0}'.format(exc)
|
||||||
|
)
|
||||||
|
return ''
|
||||||
|
|
||||||
def wheel(self, clear_load):
|
def wheel(self, clear_load):
|
||||||
'''
|
'''
|
||||||
Send a master control function back to the wheel system
|
Send a master control function back to the wheel system
|
||||||
@ -1777,6 +1865,14 @@ class ClearFuncs(object):
|
|||||||
if token['name'] not in self.opts['external_auth'][token['eauth']]:
|
if token['name'] not in self.opts['external_auth'][token['eauth']]:
|
||||||
log.warning('Authentication failure of type "token" occurred.')
|
log.warning('Authentication failure of type "token" occurred.')
|
||||||
return ''
|
return ''
|
||||||
|
good = self.ckminions.wheel_check(
|
||||||
|
self.opts['external_auth'][clear_load['eauth']][token['name']] if token['name'] in self.opts['external_auth'][clear_load['eauth']] else self.opts['external_auth'][token['eauth']]['*'],
|
||||||
|
clear_load['fun'])
|
||||||
|
if not good:
|
||||||
|
msg = ('Authentication failure of type "eauth" occurred for '
|
||||||
|
'user {0}.').format(clear_load.get('username', 'UNKNOWN'))
|
||||||
|
log.warning(msg)
|
||||||
|
return ''
|
||||||
|
|
||||||
try:
|
try:
|
||||||
fun = clear_load.pop('fun')
|
fun = clear_load.pop('fun')
|
||||||
@ -2060,7 +2156,7 @@ class ClearFuncs(object):
|
|||||||
self.opts['hash_type']
|
self.opts['hash_type']
|
||||||
)
|
)
|
||||||
|
|
||||||
# Announce the job on the event bus
|
# Announce the job on the event bus
|
||||||
self.event.fire_event(clear_load, 'new_job')
|
self.event.fire_event(clear_load, 'new_job')
|
||||||
|
|
||||||
# Verify the jid dir
|
# Verify the jid dir
|
||||||
|
@ -150,8 +150,13 @@ def latest_version(*names, **kwargs):
|
|||||||
# If there are no installed versions that are greater than or equal
|
# If there are no installed versions that are greater than or equal
|
||||||
# to the install candidate, then the candidate is an upgrade, so
|
# to the install candidate, then the candidate is an upgrade, so
|
||||||
# add it to the return dict
|
# add it to the return dict
|
||||||
if not any([compare(pkg1=x, oper='>=', pkg2=candidate)
|
if not any(
|
||||||
for x in installed]):
|
(salt.utils.compare_versions(ver1=x,
|
||||||
|
oper='>=',
|
||||||
|
ver2=candidate,
|
||||||
|
cmp_func=version_cmp)
|
||||||
|
for x in installed)
|
||||||
|
):
|
||||||
ret[name] = candidate
|
ret[name] = candidate
|
||||||
|
|
||||||
# Return a string if only one package name passed
|
# Return a string if only one package name passed
|
||||||
@ -629,7 +634,7 @@ def upgrade_available(name):
|
|||||||
return latest_version(name) != ''
|
return latest_version(name) != ''
|
||||||
|
|
||||||
|
|
||||||
def perform_cmp(pkg1='', pkg2=''):
|
def version_cmp(pkg1, pkg2):
|
||||||
'''
|
'''
|
||||||
Do a cmp-style comparison on two packages. Return -1 if pkg1 < pkg2, 0 if
|
Do a cmp-style comparison on two packages. Return -1 if pkg1 < pkg2, 0 if
|
||||||
pkg1 == pkg2, and 1 if pkg1 > pkg2. Return None if there was a problem
|
pkg1 == pkg2, and 1 if pkg1 > pkg2. Return None if there was a problem
|
||||||
@ -637,8 +642,7 @@ def perform_cmp(pkg1='', pkg2=''):
|
|||||||
|
|
||||||
CLI Example::
|
CLI Example::
|
||||||
|
|
||||||
salt '*' pkg.perform_cmp '0.2.4-0ubuntu1' '0.2.4.1-0ubuntu1'
|
salt '*' pkg.version_cmp '0.2.4-0ubuntu1' '0.2.4.1-0ubuntu1'
|
||||||
salt '*' pkg.perform_cmp pkg1='0.2.4-0ubuntu1' pkg2='0.2.4.1-0ubuntu1'
|
|
||||||
'''
|
'''
|
||||||
try:
|
try:
|
||||||
for oper, ret in (('lt', -1), ('eq', 0), ('gt', 1)):
|
for oper, ret in (('lt', -1), ('eq', 0), ('gt', 1)):
|
||||||
@ -651,18 +655,6 @@ def perform_cmp(pkg1='', pkg2=''):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def compare(pkg1='', oper='==', pkg2=''):
|
|
||||||
'''
|
|
||||||
Compare two version strings.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.compare '0.2.4-0' '<' '0.2.4.1-0'
|
|
||||||
salt '*' pkg.compare pkg1='0.2.4-0' oper='<' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.compare'](pkg1=pkg1, oper=oper, pkg2=pkg2)
|
|
||||||
|
|
||||||
|
|
||||||
def _split_repo_str(repo):
|
def _split_repo_str(repo):
|
||||||
split = sourceslist.SourceEntry(repo)
|
split = sourceslist.SourceEntry(repo)
|
||||||
return split.type, split.uri, split.dist, split.comps
|
return split.type, split.uri, split.dist, split.comps
|
||||||
|
@ -278,29 +278,3 @@ def upgrade_available(pkg):
|
|||||||
salt '*' pkg.upgrade_available <package name>
|
salt '*' pkg.upgrade_available <package name>
|
||||||
'''
|
'''
|
||||||
return pkg in list_upgrades()
|
return pkg in list_upgrades()
|
||||||
|
|
||||||
|
|
||||||
def perform_cmp(pkg1='', pkg2=''):
|
|
||||||
'''
|
|
||||||
Do a cmp-style comparison on two packages. Return -1 if pkg1 < pkg2, 0 if
|
|
||||||
pkg1 == pkg2, and 1 if pkg1 > pkg2. Return None if there was a problem
|
|
||||||
making the comparison.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.perform_cmp '0.2.4-0' '0.2.4.1-0'
|
|
||||||
salt '*' pkg.perform_cmp pkg1='0.2.4-0' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.perform_cmp'](pkg1=pkg1, pkg2=pkg2)
|
|
||||||
|
|
||||||
|
|
||||||
def compare(pkg1='', oper='==', pkg2=''):
|
|
||||||
'''
|
|
||||||
Compare two version strings.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.compare '0.2.4-0' '<' '0.2.4.1-0'
|
|
||||||
salt '*' pkg.compare pkg1='0.2.4-0' oper='<' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.compare'](pkg1=pkg1, oper=oper, pkg2=pkg2)
|
|
||||||
|
@ -312,7 +312,7 @@ def list_states(env='base'):
|
|||||||
return __context__['cp.fileclient'].list_states(env)
|
return __context__['cp.fileclient'].list_states(env)
|
||||||
|
|
||||||
|
|
||||||
def list_master(env='base'):
|
def list_master(env='base', prefix=''):
|
||||||
'''
|
'''
|
||||||
List all of the files stored on the master
|
List all of the files stored on the master
|
||||||
|
|
||||||
@ -321,10 +321,10 @@ def list_master(env='base'):
|
|||||||
salt '*' cp.list_master
|
salt '*' cp.list_master
|
||||||
'''
|
'''
|
||||||
_mk_client()
|
_mk_client()
|
||||||
return __context__['cp.fileclient'].file_list(env)
|
return __context__['cp.fileclient'].file_list(env, prefix)
|
||||||
|
|
||||||
|
|
||||||
def list_master_dirs(env='base'):
|
def list_master_dirs(env='base', prefix=''):
|
||||||
'''
|
'''
|
||||||
List all of the directories stored on the master
|
List all of the directories stored on the master
|
||||||
|
|
||||||
@ -333,7 +333,7 @@ def list_master_dirs(env='base'):
|
|||||||
salt '*' cp.list_master_dirs
|
salt '*' cp.list_master_dirs
|
||||||
'''
|
'''
|
||||||
_mk_client()
|
_mk_client()
|
||||||
return __context__['cp.fileclient'].dir_list(env)
|
return __context__['cp.fileclient'].dir_list(env, prefix)
|
||||||
|
|
||||||
|
|
||||||
def list_minion(env='base'):
|
def list_minion(env='base'):
|
||||||
@ -379,12 +379,12 @@ def push(path):
|
|||||||
'''
|
'''
|
||||||
Push a file from the minion up to the master, the file will be saved to
|
Push a file from the minion up to the master, the file will be saved to
|
||||||
the salt master in the master's minion files cachedir
|
the salt master in the master's minion files cachedir
|
||||||
(defaults to /var/cache/salt/master/minions/files)
|
(defaults to ``/var/cache/salt/master/minions/minion-id/files``)
|
||||||
|
|
||||||
Since this feature allows a minion to push a file up to the master server
|
Since this feature allows a minion to push a file up to the master server
|
||||||
it is disabled by default for security purposes. To enable add the option:
|
it is disabled by default for security purposes. To enable, set
|
||||||
file_recv: True
|
``file_recv`` to ``True`` in the master configuration file, and restart the
|
||||||
to the master configuration and restart the master
|
master.
|
||||||
|
|
||||||
CLI Example::
|
CLI Example::
|
||||||
|
|
||||||
|
@ -132,7 +132,11 @@ def latest_version(*names, **kwargs):
|
|||||||
installed = _cpv_to_version(_vartree().dep_bestmatch(name))
|
installed = _cpv_to_version(_vartree().dep_bestmatch(name))
|
||||||
avail = _cpv_to_version(_porttree().dep_bestmatch(name))
|
avail = _cpv_to_version(_porttree().dep_bestmatch(name))
|
||||||
if avail:
|
if avail:
|
||||||
if not installed or compare(pkg1=installed, oper='<', pkg2=avail):
|
if not installed \
|
||||||
|
or salt.utils.compare_versions(ver1=installed,
|
||||||
|
oper='<',
|
||||||
|
ver2=avail,
|
||||||
|
cmp_func=version_cmp):
|
||||||
ret[name] = avail
|
ret[name] = avail
|
||||||
|
|
||||||
# Return a string if only one package name passed
|
# Return a string if only one package name passed
|
||||||
@ -221,8 +225,8 @@ def porttree_matches(name):
|
|||||||
'''
|
'''
|
||||||
matches = []
|
matches = []
|
||||||
for category in _porttree().dbapi.categories:
|
for category in _porttree().dbapi.categories:
|
||||||
if _porttree().dbapi.cp_list(category+"/"+name):
|
if _porttree().dbapi.cp_list(category + "/" + name):
|
||||||
matches.append(category+"/"+name)
|
matches.append(category + "/" + name)
|
||||||
return matches
|
return matches
|
||||||
|
|
||||||
|
|
||||||
@ -276,7 +280,8 @@ def refresh_db():
|
|||||||
if 'makeconf.features_contains'in __salt__ and __salt__['makeconf.features_contains']('webrsync-gpg'):
|
if 'makeconf.features_contains'in __salt__ and __salt__['makeconf.features_contains']('webrsync-gpg'):
|
||||||
# GPG sign verify is supported only for "webrsync"
|
# GPG sign verify is supported only for "webrsync"
|
||||||
cmd = 'emerge-webrsync -q'
|
cmd = 'emerge-webrsync -q'
|
||||||
if salt.utils.which('emerge-delta-webrsync'): # We prefer 'delta-webrsync' to 'webrsync'
|
# We prefer 'delta-webrsync' to 'webrsync'
|
||||||
|
if salt.utils.which('emerge-delta-webrsync'):
|
||||||
cmd = 'emerge-delta-webrsync -q'
|
cmd = 'emerge-delta-webrsync -q'
|
||||||
return __salt__['cmd.retcode'](cmd) == 0
|
return __salt__['cmd.retcode'](cmd) == 0
|
||||||
else:
|
else:
|
||||||
@ -284,7 +289,8 @@ def refresh_db():
|
|||||||
return True
|
return True
|
||||||
# We fall back to "webrsync" if "rsync" fails for some reason
|
# We fall back to "webrsync" if "rsync" fails for some reason
|
||||||
cmd = 'emerge-webrsync -q'
|
cmd = 'emerge-webrsync -q'
|
||||||
if salt.utils.which('emerge-delta-webrsync'): # We prefer 'delta-webrsync' to 'webrsync'
|
# We prefer 'delta-webrsync' to 'webrsync'
|
||||||
|
if salt.utils.which('emerge-delta-webrsync'):
|
||||||
cmd = 'emerge-delta-webrsync -q'
|
cmd = 'emerge-delta-webrsync -q'
|
||||||
return __salt__['cmd.retcode'](cmd) == 0
|
return __salt__['cmd.retcode'](cmd) == 0
|
||||||
|
|
||||||
@ -413,7 +419,7 @@ def install(name=None,
|
|||||||
for param, version_num in pkg_params.iteritems():
|
for param, version_num in pkg_params.iteritems():
|
||||||
original_param = param
|
original_param = param
|
||||||
param = _p_to_cp(param)
|
param = _p_to_cp(param)
|
||||||
if param == None:
|
if param is None:
|
||||||
raise portage.dep.InvalidAtom(original_param)
|
raise portage.dep.InvalidAtom(original_param)
|
||||||
|
|
||||||
if version_num is None:
|
if version_num is None:
|
||||||
@ -442,12 +448,12 @@ def install(name=None,
|
|||||||
__salt__['portage_config.append_use_flags'](target[1:-1])
|
__salt__['portage_config.append_use_flags'](target[1:-1])
|
||||||
new = __salt__['portage_config.get_flags_from_package_conf']('use', target[1:-1])
|
new = __salt__['portage_config.get_flags_from_package_conf']('use', target[1:-1])
|
||||||
if old != new:
|
if old != new:
|
||||||
changes[param+'-USE'] = {'old': old, 'new': new}
|
changes[param + '-USE'] = {'old': old, 'new': new}
|
||||||
target = target[:target.rfind('[')] + '"'
|
target = target[:target.rfind('[')] + '"'
|
||||||
|
|
||||||
if keyword != None:
|
if keyword is not None:
|
||||||
__salt__['portage_config.append_to_package_conf']('accept_keywords', target[1:-1], ['~ARCH'])
|
__salt__['portage_config.append_to_package_conf']('accept_keywords', target[1:-1], ['~ARCH'])
|
||||||
changes[param+'-ACCEPT_KEYWORD'] = {'old': '', 'new': '~ARCH'}
|
changes[param + '-ACCEPT_KEYWORD'] = {'old': '', 'new': '~ARCH'}
|
||||||
|
|
||||||
targets.append(target)
|
targets.append(target)
|
||||||
else:
|
else:
|
||||||
@ -571,7 +577,7 @@ def remove(name=None, slot=None, fromrepo=None, pkgs=None, **kwargs):
|
|||||||
targets = ['{0}:{1}'.format(fullatom, slot)]
|
targets = ['{0}:{1}'.format(fullatom, slot)]
|
||||||
if fromrepo is not None:
|
if fromrepo is not None:
|
||||||
targets = ['{0}::{1}'.format(fullatom, fromrepo)]
|
targets = ['{0}::{1}'.format(fullatom, fromrepo)]
|
||||||
targets = [ fullatom ]
|
targets = [fullatom]
|
||||||
else:
|
else:
|
||||||
targets = [x for x in pkg_params if x in old]
|
targets = [x for x in pkg_params if x in old]
|
||||||
|
|
||||||
@ -656,7 +662,7 @@ def depclean(name=None, slot=None, fromrepo=None, pkgs=None):
|
|||||||
targets = ['{0}:{1}'.format(fullatom, slot)]
|
targets = ['{0}:{1}'.format(fullatom, slot)]
|
||||||
if fromrepo is not None:
|
if fromrepo is not None:
|
||||||
targets = ['{0}::{1}'.format(fullatom, fromrepo)]
|
targets = ['{0}::{1}'.format(fullatom, fromrepo)]
|
||||||
targets = [ fullatom ]
|
targets = [fullatom]
|
||||||
else:
|
else:
|
||||||
targets = [x for x in pkg_params if x in old]
|
targets = [x for x in pkg_params if x in old]
|
||||||
|
|
||||||
@ -667,7 +673,7 @@ def depclean(name=None, slot=None, fromrepo=None, pkgs=None):
|
|||||||
return __salt__['pkg_resource.find_changes'](old, new)
|
return __salt__['pkg_resource.find_changes'](old, new)
|
||||||
|
|
||||||
|
|
||||||
def perform_cmp(pkg1='', pkg2=''):
|
def version_cmp(pkg1, pkg2):
|
||||||
'''
|
'''
|
||||||
Do a cmp-style comparison on two packages. Return -1 if pkg1 < pkg2, 0 if
|
Do a cmp-style comparison on two packages. Return -1 if pkg1 < pkg2, 0 if
|
||||||
pkg1 == pkg2, and 1 if pkg1 > pkg2. Return None if there was a problem
|
pkg1 == pkg2, and 1 if pkg1 > pkg2. Return None if there was a problem
|
||||||
@ -675,8 +681,7 @@ def perform_cmp(pkg1='', pkg2=''):
|
|||||||
|
|
||||||
CLI Example::
|
CLI Example::
|
||||||
|
|
||||||
salt '*' pkg.perform_cmp '0.2.4-0' '0.2.4.1-0'
|
salt '*' pkg.version_cmp '0.2.4-0' '0.2.4.1-0'
|
||||||
salt '*' pkg.perform_cmp pkg1='0.2.4-0' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
'''
|
||||||
regex = r'^~?([^:\[]+):?[^\[]*\[?.*$'
|
regex = r'^~?([^:\[]+):?[^\[]*\[?.*$'
|
||||||
ver1 = re.match(regex, pkg1)
|
ver1 = re.match(regex, pkg1)
|
||||||
@ -687,18 +692,6 @@ def perform_cmp(pkg1='', pkg2=''):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def compare(pkg1='', oper='==', pkg2=''):
|
|
||||||
'''
|
|
||||||
Compare two version strings.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.compare '0.2.4-0' '<' '0.2.4.1-0'
|
|
||||||
salt '*' pkg.compare pkg1='0.2.4-0' oper='<' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.compare'](pkg1=pkg1, oper=oper, pkg2=pkg2)
|
|
||||||
|
|
||||||
|
|
||||||
def version_clean(version):
|
def version_clean(version):
|
||||||
'''
|
'''
|
||||||
Clean the version string removing extra data.
|
Clean the version string removing extra data.
|
||||||
@ -752,7 +745,8 @@ def check_extra_requirements(pkgname, pkgver):
|
|||||||
|
|
||||||
des_uses = set(portage.dep.dep_getusedeps(atom))
|
des_uses = set(portage.dep.dep_getusedeps(atom))
|
||||||
cur_use = cur_use.split()
|
cur_use = cur_use.split()
|
||||||
if len([ x for x in des_uses.difference(cur_use) if x[0]!='-' or x[1:] in cur_use ]) > 0:
|
if len([x for x in des_uses.difference(cur_use)
|
||||||
|
if x[0] != '-' or x[1:] in cur_use]) > 0:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if keyword:
|
if keyword:
|
||||||
|
@ -391,32 +391,6 @@ def rehash():
|
|||||||
__salt__['cmd.run_all']('rehash')
|
__salt__['cmd.run_all']('rehash')
|
||||||
|
|
||||||
|
|
||||||
def perform_cmp(pkg1='', pkg2=''):
|
|
||||||
'''
|
|
||||||
Do a cmp-style comparison on two packages. Return -1 if pkg1 < pkg2, 0 if
|
|
||||||
pkg1 == pkg2, and 1 if pkg1 > pkg2. Return None if there was a problem
|
|
||||||
making the comparison.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.perform_cmp '0.2.4-0' '0.2.4.1-0'
|
|
||||||
salt '*' pkg.perform_cmp pkg1='0.2.4-0' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.perform_cmp'](pkg1=pkg1, pkg2=pkg2)
|
|
||||||
|
|
||||||
|
|
||||||
def compare(pkg1='', oper='==', pkg2=''):
|
|
||||||
'''
|
|
||||||
Compare two version strings.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.compare '0.2.4-0' '<' '0.2.4.1-0'
|
|
||||||
salt '*' pkg.compare pkg1='0.2.4-0' oper='<' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.compare'](pkg1=pkg1, oper=oper, pkg2=pkg2)
|
|
||||||
|
|
||||||
|
|
||||||
def file_list(*packages):
|
def file_list(*packages):
|
||||||
'''
|
'''
|
||||||
List the files that belong to a package. Not specifying any packages will
|
List the files that belong to a package. Not specifying any packages will
|
||||||
|
@ -216,3 +216,30 @@ def ls(): # pylint: disable=C0103
|
|||||||
salt '*' grains.ls
|
salt '*' grains.ls
|
||||||
'''
|
'''
|
||||||
return sorted(__grains__)
|
return sorted(__grains__)
|
||||||
|
|
||||||
|
|
||||||
|
def filter_by(lookup_dict, grain='os_family'):
|
||||||
|
'''
|
||||||
|
Look up the given grain in a given dictionary for the current OS and return
|
||||||
|
the result
|
||||||
|
|
||||||
|
Although this may occasionally be useful at the CLI, the primary intent of
|
||||||
|
this function is for use in Jinja to make short work of creating lookup
|
||||||
|
tables for OS-specific data. For example::
|
||||||
|
|
||||||
|
{% set pkg_table = {
|
||||||
|
'Debian': {'name': 'apache2'},
|
||||||
|
'RedHat': {'name': 'httpd'},
|
||||||
|
} %}
|
||||||
|
{% set pkg = salt['grains.filter_by'](pkg_table) %}
|
||||||
|
|
||||||
|
myapache:
|
||||||
|
pkg:
|
||||||
|
- installed
|
||||||
|
- name: {{ pkg.name }}
|
||||||
|
|
||||||
|
CLI Example::
|
||||||
|
|
||||||
|
salt '*' grains.filter_by '{Debian: Debheads rule, RedHat: I love my hat}'
|
||||||
|
'''
|
||||||
|
return lookup_dict.get(__grains__[grain], None)
|
||||||
|
@ -222,29 +222,3 @@ def purge(name=None, pkgs=None, **kwargs):
|
|||||||
salt '*' pkg.purge pkgs='["foo", "bar"]'
|
salt '*' pkg.purge pkgs='["foo", "bar"]'
|
||||||
'''
|
'''
|
||||||
return remove(name=name, pkgs=pkgs)
|
return remove(name=name, pkgs=pkgs)
|
||||||
|
|
||||||
|
|
||||||
def perform_cmp(pkg1='', pkg2=''):
|
|
||||||
'''
|
|
||||||
Do a cmp-style comparison on two packages. Return -1 if pkg1 < pkg2, 0 if
|
|
||||||
pkg1 == pkg2, and 1 if pkg1 > pkg2. Return None if there was a problem
|
|
||||||
making the comparison.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.perform_cmp '0.2.4' '0.2.4.1'
|
|
||||||
salt '*' pkg.perform_cmp pkg1='0.2.4' pkg2='0.2.4.1'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.perform_cmp'](pkg1=pkg1, pkg2=pkg2)
|
|
||||||
|
|
||||||
|
|
||||||
def compare(pkg1='', oper='==', pkg2=''):
|
|
||||||
'''
|
|
||||||
Compare two version strings.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.compare '0.2.4' '<' '0.2.4.1'
|
|
||||||
salt '*' pkg.compare pkg1='0.2.4' oper='<' pkg2='0.2.4.1'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.compare'](pkg1=pkg1, oper=oper, pkg2=pkg2)
|
|
||||||
|
@ -396,32 +396,6 @@ def purge(name=None, pkgs=None, **kwargs):
|
|||||||
return _uninstall(action='purge', name=name, pkgs=pkgs)
|
return _uninstall(action='purge', name=name, pkgs=pkgs)
|
||||||
|
|
||||||
|
|
||||||
def perform_cmp(pkg1='', pkg2=''):
|
|
||||||
'''
|
|
||||||
Do a cmp-style comparison on two packages. Return -1 if pkg1 < pkg2, 0 if
|
|
||||||
pkg1 == pkg2, and 1 if pkg1 > pkg2. Return None if there was a problem
|
|
||||||
making the comparison.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.perform_cmp '0.2.4-0' '0.2.4.1-0'
|
|
||||||
salt '*' pkg.perform_cmp pkg1='0.2.4-0' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.perform_cmp'](pkg1=pkg1, pkg2=pkg2)
|
|
||||||
|
|
||||||
|
|
||||||
def compare(pkg1='', oper='==', pkg2=''):
|
|
||||||
'''
|
|
||||||
Compare two version strings.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.compare '0.2.4-0' '<' '0.2.4.1-0'
|
|
||||||
salt '*' pkg.compare pkg1='0.2.4-0' oper='<' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.compare'](pkg1=pkg1, oper=oper, pkg2=pkg2)
|
|
||||||
|
|
||||||
|
|
||||||
def file_list(*packages):
|
def file_list(*packages):
|
||||||
'''
|
'''
|
||||||
List the files that belong to a package. Not specifying any packages will
|
List the files that belong to a package. Not specifying any packages will
|
||||||
|
@ -3,7 +3,6 @@ Resources needed by pkg providers
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
# Import python libs
|
# Import python libs
|
||||||
import distutils.version # pylint: disable=E0611
|
|
||||||
import fnmatch
|
import fnmatch
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
@ -97,7 +96,8 @@ def _parse_pkg_meta(path):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
continue
|
continue
|
||||||
if arch:
|
if arch:
|
||||||
name += ':{0}'.format(arch)
|
if cpuarch == 'x86_64' and arch != 'amd64':
|
||||||
|
name += ':{0}'.format(arch)
|
||||||
return name, version
|
return name, version
|
||||||
|
|
||||||
if __grains__['os_family'] in ('Suse', 'RedHat', 'Mandriva'):
|
if __grains__['os_family'] in ('Suse', 'RedHat', 'Mandriva'):
|
||||||
@ -418,62 +418,10 @@ def find_changes(old=None, new=None):
|
|||||||
return pkgs
|
return pkgs
|
||||||
|
|
||||||
|
|
||||||
def perform_cmp(pkg1='', pkg2=''):
|
|
||||||
'''
|
|
||||||
Compares two version strings using distutils.version.LooseVersion. This is
|
|
||||||
a fallback for providers which don't have a version comparison utility
|
|
||||||
built into them. Return -1 if version1 < version2, 0 if version1 ==
|
|
||||||
version2, and 1 if version1 > version2. Return None if there was a problem
|
|
||||||
making the comparison.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg_resource.perform_cmp
|
|
||||||
'''
|
|
||||||
try:
|
|
||||||
if distutils.version.LooseVersion(pkg1) < \
|
|
||||||
distutils.version.LooseVersion(pkg2):
|
|
||||||
return -1
|
|
||||||
elif distutils.version.LooseVersion(pkg1) == \
|
|
||||||
distutils.version.LooseVersion(pkg2):
|
|
||||||
return 0
|
|
||||||
elif distutils.version.LooseVersion(pkg1) > \
|
|
||||||
distutils.version.LooseVersion(pkg2):
|
|
||||||
return 1
|
|
||||||
except Exception as e:
|
|
||||||
log.exception(e)
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def compare(pkg1='', oper='==', pkg2=''):
|
|
||||||
'''
|
|
||||||
Package version comparison function.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg_resource.compare
|
|
||||||
'''
|
|
||||||
cmp_map = {'<': (-1,), '<=': (-1, 0), '==': (0,),
|
|
||||||
'>=': (0, 1), '>': (1,)}
|
|
||||||
if oper not in ['!='] + cmp_map.keys():
|
|
||||||
log.error('Invalid operator "{0}" for package '
|
|
||||||
'comparison'.format(oper))
|
|
||||||
return False
|
|
||||||
|
|
||||||
cmp_result = __salt__['pkg.perform_cmp'](pkg1, pkg2)
|
|
||||||
if cmp_result is None:
|
|
||||||
return False
|
|
||||||
|
|
||||||
if oper == '!=':
|
|
||||||
return cmp_result not in cmp_map['==']
|
|
||||||
else:
|
|
||||||
return cmp_result in cmp_map[oper]
|
|
||||||
|
|
||||||
|
|
||||||
def version_clean(version):
|
def version_clean(version):
|
||||||
'''
|
'''
|
||||||
Clean the version string removing extra data.
|
Clean the version string removing extra data.
|
||||||
This function will simply try to call "pkg.version_clean".
|
This function will simply try to call ``pkg.version_clean``.
|
||||||
|
|
||||||
CLI Example::
|
CLI Example::
|
||||||
|
|
||||||
|
@ -423,32 +423,6 @@ def rehash():
|
|||||||
__salt__['cmd.run']('rehash')
|
__salt__['cmd.run']('rehash')
|
||||||
|
|
||||||
|
|
||||||
def perform_cmp(pkg1='', pkg2=''):
|
|
||||||
'''
|
|
||||||
Do a cmp-style comparison on two packages. Return -1 if pkg1 < pkg2, 0 if
|
|
||||||
pkg1 == pkg2, and 1 if pkg1 > pkg2. Return None if there was a problem
|
|
||||||
making the comparison.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.perform_cmp '0.2.4-0' '0.2.4.1-0'
|
|
||||||
salt '*' pkg.perform_cmp pkg1='0.2.4-0' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.perform_cmp'](pkg1=pkg1, pkg2=pkg2)
|
|
||||||
|
|
||||||
|
|
||||||
def compare(pkg1='', oper='==', pkg2=''):
|
|
||||||
'''
|
|
||||||
Compare two version strings.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.compare '0.2.4-0' '<' '0.2.4.1-0'
|
|
||||||
salt '*' pkg.compare pkg1='0.2.4-0' oper='<' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.compare'](pkg1=pkg1, oper=oper, pkg2=pkg2)
|
|
||||||
|
|
||||||
|
|
||||||
def file_list(package):
|
def file_list(package):
|
||||||
'''
|
'''
|
||||||
List the files that belong to a package.
|
List the files that belong to a package.
|
||||||
|
@ -857,29 +857,3 @@ def updating(pkg_name, filedate=None, filename=None):
|
|||||||
|
|
||||||
cmd = 'pkg updating {0} {1}'.format(opts, pkg_name)
|
cmd = 'pkg updating {0} {1}'.format(opts, pkg_name)
|
||||||
return __salt__['cmd.run'](cmd)
|
return __salt__['cmd.run'](cmd)
|
||||||
|
|
||||||
|
|
||||||
def perform_cmp(pkg1='', pkg2=''):
|
|
||||||
'''
|
|
||||||
Do a cmp-style comparison on two packages. Return -1 if pkg1 < pkg2, 0 if
|
|
||||||
pkg1 == pkg2, and 1 if pkg1 > pkg2. Return None if there was a problem
|
|
||||||
making the comparison.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.perform_cmp '0.2.4-0' '0.2.4.1-0'
|
|
||||||
salt '*' pkg.perform_cmp pkg1='0.2.4-0' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.perform_cmp'](pkg1=pkg1, pkg2=pkg2)
|
|
||||||
|
|
||||||
|
|
||||||
def compare(pkg1='', oper='==', pkg2=''):
|
|
||||||
'''
|
|
||||||
Compare two version strings.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.compare '0.2.4-0' '<' '0.2.4.1-0'
|
|
||||||
salt '*' pkg.compare pkg1='0.2.4-0' oper='<' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.compare'](pkg1=pkg1, oper=oper, pkg2=pkg2)
|
|
||||||
|
@ -194,7 +194,9 @@ def latest_version(*names, **kwargs):
|
|||||||
if name in names:
|
if name in names:
|
||||||
cver = pkgs.get(name, '')
|
cver = pkgs.get(name, '')
|
||||||
nver = version_rev.split(',')[0]
|
nver = version_rev.split(',')[0]
|
||||||
if not cver or compare(pkg1=cver, oper='<', pkg2=nver):
|
if not cver or salt.utils.compare_versions(ver1=cver,
|
||||||
|
oper='<',
|
||||||
|
ver2=nver):
|
||||||
# Remove revision for version comparison
|
# Remove revision for version comparison
|
||||||
ret[name] = version_rev
|
ret[name] = version_rev
|
||||||
|
|
||||||
@ -326,29 +328,3 @@ def purge(name=None, pkgs=None, **kwargs):
|
|||||||
salt '*' pkg.purge pkgs='["foo", "bar"]'
|
salt '*' pkg.purge pkgs='["foo", "bar"]'
|
||||||
'''
|
'''
|
||||||
return remove(name=name, pkgs=pkgs)
|
return remove(name=name, pkgs=pkgs)
|
||||||
|
|
||||||
|
|
||||||
def perform_cmp(pkg1='', pkg2=''):
|
|
||||||
'''
|
|
||||||
Do a cmp-style comparison on two packages. Return -1 if pkg1 < pkg2, 0 if
|
|
||||||
pkg1 == pkg2, and 1 if pkg1 > pkg2. Return None if there was a problem
|
|
||||||
making the comparison.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.perform_cmp '0.2.4-0' '0.2.4.1-0'
|
|
||||||
salt '*' pkg.perform_cmp pkg1='0.2.4-0' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.perform_cmp'](pkg1=pkg1, pkg2=pkg2)
|
|
||||||
|
|
||||||
|
|
||||||
def compare(pkg1='', oper='==', pkg2=''):
|
|
||||||
'''
|
|
||||||
Compare two version strings.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.compare '0.2.4-0' '<' '0.2.4.1-0'
|
|
||||||
salt '*' pkg.compare pkg1='0.2.4-0' oper='<' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.compare'](pkg1=pkg1, oper=oper, pkg2=pkg2)
|
|
||||||
|
@ -436,29 +436,3 @@ def purge(name=None, pkgs=None, **kwargs):
|
|||||||
salt '*' pkg.purge pkgs='["foo", "bar"]'
|
salt '*' pkg.purge pkgs='["foo", "bar"]'
|
||||||
'''
|
'''
|
||||||
return remove(name=name, pkgs=pkgs, **kwargs)
|
return remove(name=name, pkgs=pkgs, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def perform_cmp(pkg1='', pkg2=''):
|
|
||||||
'''
|
|
||||||
Do a cmp-style comparison on two packages. Return -1 if pkg1 < pkg2, 0 if
|
|
||||||
pkg1 == pkg2, and 1 if pkg1 > pkg2. Return None if there was a problem
|
|
||||||
making the comparison.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.perform_cmp '0.2.4-0' '0.2.4.1-0'
|
|
||||||
salt '*' pkg.perform_cmp pkg1='0.2.4-0' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.perform_cmp'](pkg1=pkg1, pkg2=pkg2)
|
|
||||||
|
|
||||||
|
|
||||||
def compare(pkg1='', oper='==', pkg2=''):
|
|
||||||
'''
|
|
||||||
Compare two version strings.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.compare '0.2.4-0' '<' '0.2.4.1-0'
|
|
||||||
salt '*' pkg.compare pkg1='0.2.4-0' oper='<' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.compare'](pkg1=pkg1, oper=oper, pkg2=pkg2)
|
|
||||||
|
@ -706,29 +706,3 @@ def _get_latest_pkg_version(pkginfo):
|
|||||||
return pkginfo.keys().pop()
|
return pkginfo.keys().pop()
|
||||||
pkgkeys = pkginfo.keys()
|
pkgkeys = pkginfo.keys()
|
||||||
return sorted(pkgkeys, cmp=_reverse_cmp_pkg_versions).pop()
|
return sorted(pkgkeys, cmp=_reverse_cmp_pkg_versions).pop()
|
||||||
|
|
||||||
|
|
||||||
def perform_cmp(pkg1='', pkg2=''):
|
|
||||||
'''
|
|
||||||
Do a cmp-style comparison on two packages. Return -1 if pkg1 < pkg2, 0 if
|
|
||||||
pkg1 == pkg2, and 1 if pkg1 > pkg2. Return None if there was a problem
|
|
||||||
making the comparison.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.perform_cmp '0.2.4-0' '0.2.4.1-0'
|
|
||||||
salt '*' pkg.perform_cmp pkg1='0.2.4-0' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.perform_cmp'](pkg1=pkg1, pkg2=pkg2)
|
|
||||||
|
|
||||||
|
|
||||||
def compare(pkg1='', oper='==', pkg2=''):
|
|
||||||
'''
|
|
||||||
Compare two version strings.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.compare '0.2.4-0' '<' '0.2.4.1-0'
|
|
||||||
salt '*' pkg.compare pkg1='0.2.4-0' oper='<' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.compare'](pkg1=pkg1, oper=oper, pkg2=pkg2)
|
|
||||||
|
@ -1039,32 +1039,6 @@ def _parse_repo_file(filename):
|
|||||||
return (header, repos)
|
return (header, repos)
|
||||||
|
|
||||||
|
|
||||||
def perform_cmp(pkg1='', pkg2=''):
|
|
||||||
'''
|
|
||||||
Do a cmp-style comparison on two packages. Return -1 if pkg1 < pkg2, 0 if
|
|
||||||
pkg1 == pkg2, and 1 if pkg1 > pkg2. Return None if there was a problem
|
|
||||||
making the comparison.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.perform_cmp '0.2.4-0' '0.2.4.1-0'
|
|
||||||
salt '*' pkg.perform_cmp pkg1='0.2.4-0' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.perform_cmp'](pkg1=pkg1, pkg2=pkg2)
|
|
||||||
|
|
||||||
|
|
||||||
def compare(pkg1='', oper='==', pkg2=''):
|
|
||||||
'''
|
|
||||||
Compare two version strings.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.compare '0.2.4-0' '<' '0.2.4.1-0'
|
|
||||||
salt '*' pkg.compare pkg1='0.2.4-0' oper='<' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.compare'](pkg1=pkg1, oper=oper, pkg2=pkg2)
|
|
||||||
|
|
||||||
|
|
||||||
def file_list(*packages):
|
def file_list(*packages):
|
||||||
'''
|
'''
|
||||||
List the files that belong to a package. Not specifying any packages will
|
List the files that belong to a package. Not specifying any packages will
|
||||||
|
@ -505,29 +505,3 @@ def purge(name=None, pkgs=None, **kwargs):
|
|||||||
salt '*' pkg.purge pkgs='["foo", "bar"]'
|
salt '*' pkg.purge pkgs='["foo", "bar"]'
|
||||||
'''
|
'''
|
||||||
return remove(name=name, pkgs=pkgs)
|
return remove(name=name, pkgs=pkgs)
|
||||||
|
|
||||||
|
|
||||||
def perform_cmp(pkg1='', pkg2=''):
|
|
||||||
'''
|
|
||||||
Do a cmp-style comparison on two packages. Return -1 if pkg1 < pkg2, 0 if
|
|
||||||
pkg1 == pkg2, and 1 if pkg1 > pkg2. Return None if there was a problem
|
|
||||||
making the comparison.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.perform_cmp '0.2.4-0' '0.2.4.1-0'
|
|
||||||
salt '*' pkg.perform_cmp pkg1='0.2.4-0' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.perform_cmp'](pkg1=pkg1, pkg2=pkg2)
|
|
||||||
|
|
||||||
|
|
||||||
def compare(pkg1='', oper='==', pkg2=''):
|
|
||||||
'''
|
|
||||||
Compare two version strings.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.compare '0.2.4-0' '<' '0.2.4.1-0'
|
|
||||||
salt '*' pkg.compare pkg1='0.2.4-0' oper='<' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.compare'](pkg1=pkg1, oper=oper, pkg2=pkg2)
|
|
||||||
|
@ -419,29 +419,3 @@ def purge(name=None, pkgs=None, **kwargs):
|
|||||||
salt '*' pkg.purge pkgs='["foo", "bar"]'
|
salt '*' pkg.purge pkgs='["foo", "bar"]'
|
||||||
'''
|
'''
|
||||||
return _uninstall(action='purge', name=name, pkgs=pkgs)
|
return _uninstall(action='purge', name=name, pkgs=pkgs)
|
||||||
|
|
||||||
|
|
||||||
def perform_cmp(pkg1='', pkg2=''):
|
|
||||||
'''
|
|
||||||
Do a cmp-style comparison on two packages. Return -1 if pkg1 < pkg2, 0 if
|
|
||||||
pkg1 == pkg2, and 1 if pkg1 > pkg2. Return None if there was a problem
|
|
||||||
making the comparison.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.perform_cmp '0.2.4-0' '0.2.4.1-0'
|
|
||||||
salt '*' pkg.perform_cmp pkg1='0.2.4-0' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.perform_cmp'](pkg1=pkg1, pkg2=pkg2)
|
|
||||||
|
|
||||||
|
|
||||||
def compare(pkg1='', oper='==', pkg2=''):
|
|
||||||
'''
|
|
||||||
Compare two version strings.
|
|
||||||
|
|
||||||
CLI Example::
|
|
||||||
|
|
||||||
salt '*' pkg.compare '0.2.4-0' '<' '0.2.4.1-0'
|
|
||||||
salt '*' pkg.compare pkg1='0.2.4-0' oper='<' pkg2='0.2.4.1-0'
|
|
||||||
'''
|
|
||||||
return __salt__['pkg_resource.compare'](pkg1=pkg1, oper=oper, pkg2=pkg2)
|
|
||||||
|
@ -58,49 +58,6 @@ def _get_ref(repo, short):
|
|||||||
return ref
|
return ref
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def _wait_lock(lk_fn, dest):
|
|
||||||
'''
|
|
||||||
If the write lock is there, check to see if the file is actually being
|
|
||||||
written. If there is no change in the file size after a short sleep,
|
|
||||||
remove the lock and move forward.
|
|
||||||
'''
|
|
||||||
if not os.path.isfile(lk_fn):
|
|
||||||
return False
|
|
||||||
if not os.path.isfile(dest):
|
|
||||||
# The dest is not here, sleep for a bit, if the dest is not here yet
|
|
||||||
# kill the lockfile and start the write
|
|
||||||
time.sleep(1)
|
|
||||||
if not os.path.isfile(dest):
|
|
||||||
try:
|
|
||||||
os.remove(lk_fn)
|
|
||||||
except (OSError, IOError):
|
|
||||||
pass
|
|
||||||
return False
|
|
||||||
# There is a lock file, the dest is there, stat the dest, sleep and check
|
|
||||||
# that the dest is being written, if it is not being written kill the lock
|
|
||||||
# file and continue. Also check if the lock file is gone.
|
|
||||||
s_count = 0
|
|
||||||
s_size = os.stat(dest).st_size
|
|
||||||
while True:
|
|
||||||
time.sleep(1)
|
|
||||||
if not os.path.isfile(lk_fn):
|
|
||||||
return False
|
|
||||||
size = os.stat(dest).st_size
|
|
||||||
if size == s_size:
|
|
||||||
s_count += 1
|
|
||||||
if s_count >= 3:
|
|
||||||
# The file is not being written to, kill the lock and proceed
|
|
||||||
try:
|
|
||||||
os.remove(lk_fn)
|
|
||||||
except (OSError, IOError):
|
|
||||||
pass
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
s_size = size
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def init(branch, repo_location):
|
def init(branch, repo_location):
|
||||||
'''
|
'''
|
||||||
Return the git repo object for this session
|
Return the git repo object for this session
|
||||||
@ -125,6 +82,7 @@ def init(branch, repo_location):
|
|||||||
repo.create_remote('origin', repo_location)
|
repo.create_remote('origin', repo_location)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
repo.git.fetch()
|
||||||
return repo
|
return repo
|
||||||
|
|
||||||
|
|
||||||
@ -141,14 +99,7 @@ def update(branch, repo_location):
|
|||||||
except git.exc.GitCommandError as e:
|
except git.exc.GitCommandError as e:
|
||||||
logging.error('Unable to checkout branch {0}: {1}'.format(branch, e))
|
logging.error('Unable to checkout branch {0}: {1}'.format(branch, e))
|
||||||
return False
|
return False
|
||||||
lk_fn = os.path.join(repo.working_dir, 'update.lk')
|
|
||||||
with salt.utils.fopen(lk_fn, 'w+') as fp_:
|
|
||||||
fp_.write(str(pid))
|
|
||||||
repo.git.pull()
|
repo.git.pull()
|
||||||
try:
|
|
||||||
os.remove(lk_fn)
|
|
||||||
except (OSError, IOError):
|
|
||||||
pass
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,11 +2,16 @@
|
|||||||
Execute salt convenience routines
|
Execute salt convenience routines
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
# Import python libs
|
||||||
|
import multiprocessing
|
||||||
|
import datetime
|
||||||
|
|
||||||
# Import salt libs
|
# Import salt libs
|
||||||
import salt.loader
|
import salt.loader
|
||||||
import salt.exceptions
|
import salt.exceptions
|
||||||
import salt.utils
|
import salt.utils
|
||||||
import salt.minion
|
import salt.minion
|
||||||
|
import salt.utils.event
|
||||||
|
|
||||||
|
|
||||||
class RunnerClient(object):
|
class RunnerClient(object):
|
||||||
@ -17,6 +22,23 @@ class RunnerClient(object):
|
|||||||
self.opts = opts
|
self.opts = opts
|
||||||
self.functions = salt.loader.runner(opts)
|
self.functions = salt.loader.runner(opts)
|
||||||
|
|
||||||
|
def _proc_runner(self, tag, fun, arg, kwarg):
|
||||||
|
'''
|
||||||
|
Run this method in a multiprocess target to execute the runner in a
|
||||||
|
multiprocess and fire the return data on the event bus
|
||||||
|
'''
|
||||||
|
salt.utils.daemonize()
|
||||||
|
data = {}
|
||||||
|
try:
|
||||||
|
data['ret'] = self.cmd(fun, arg, kwarg)
|
||||||
|
except Exception as exc:
|
||||||
|
data['ret'] = 'Exception occured in runner {0}: {1}'.format(
|
||||||
|
fun,
|
||||||
|
exc,
|
||||||
|
)
|
||||||
|
event = salt.utils.event.MasterEvent(self.opts['sock_dir'])
|
||||||
|
event.fire_event(data, tag)
|
||||||
|
|
||||||
def _verify_fun(self, fun):
|
def _verify_fun(self, fun):
|
||||||
'''
|
'''
|
||||||
Check that the function passed really exists
|
Check that the function passed really exists
|
||||||
@ -57,6 +79,19 @@ class RunnerClient(object):
|
|||||||
ret = l_fun(*f_call.get('args', ()), **f_call.get('kwargs', {}))
|
ret = l_fun(*f_call.get('args', ()), **f_call.get('kwargs', {}))
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
def async(self, fun, arg, kwarg=None):
|
||||||
|
'''
|
||||||
|
Execute the runner in a multiprocess and return the event tag to use
|
||||||
|
to watch for the return
|
||||||
|
'''
|
||||||
|
tag = '{0:%Y%m%d%H%M%S%f}'.format(datetime.datetime.now())
|
||||||
|
tag[20] = 'r'
|
||||||
|
proc = multiprocessing.Process(
|
||||||
|
target=self._proc_runner,
|
||||||
|
args=(tag, fun, arg, kwarg))
|
||||||
|
proc.start()
|
||||||
|
return tag
|
||||||
|
|
||||||
|
|
||||||
class Runner(RunnerClient):
|
class Runner(RunnerClient):
|
||||||
'''
|
'''
|
||||||
|
@ -21,7 +21,7 @@ import salt.minion
|
|||||||
|
|
||||||
def decode_list(data):
|
def decode_list(data):
|
||||||
'''
|
'''
|
||||||
JSON decodes as unicode, Jinja needs raw strings...
|
JSON decodes as unicode, Jinja needs bytes...
|
||||||
'''
|
'''
|
||||||
rv = []
|
rv = []
|
||||||
for item in data:
|
for item in data:
|
||||||
@ -37,25 +37,25 @@ def decode_list(data):
|
|||||||
|
|
||||||
def decode_dict(data):
|
def decode_dict(data):
|
||||||
'''
|
'''
|
||||||
JSON decodes as unicode, Jinja needs raw strings...
|
JSON decodes as unicode, Jinja needs bytes...
|
||||||
'''
|
'''
|
||||||
rv = {}
|
rv = {}
|
||||||
for key, value in data.iteritems():
|
for key, value in data.iteritems():
|
||||||
if isinstance(key, unicode):
|
if isinstance(key, unicode):
|
||||||
key = key.encode('utf-8')
|
key = key.encode('utf-8')
|
||||||
if isinstance(value, unicode):
|
if isinstance(value, unicode):
|
||||||
value = value.encode('utf-8')
|
value = value.encode('utf-8')
|
||||||
elif isinstance(value, list):
|
elif isinstance(value, list):
|
||||||
value = decode_list(value)
|
value = decode_list(value)
|
||||||
elif isinstance(value, dict):
|
elif isinstance(value, dict):
|
||||||
value = decode_dict(value)
|
value = decode_dict(value)
|
||||||
rv[key] = value
|
rv[key] = value
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
|
|
||||||
class SSH(object):
|
class SSH(object):
|
||||||
'''
|
'''
|
||||||
Create an ssh execution system
|
Create an SSH execution system
|
||||||
'''
|
'''
|
||||||
def __init__(self, opts):
|
def __init__(self, opts):
|
||||||
self.opts = opts
|
self.opts = opts
|
||||||
@ -85,7 +85,7 @@ class SSH(object):
|
|||||||
|
|
||||||
def get_pubkey(self):
|
def get_pubkey(self):
|
||||||
'''
|
'''
|
||||||
Return the keystring for the ssh public key
|
Return the keystring for the SSH public key
|
||||||
'''
|
'''
|
||||||
priv = self.opts.get(
|
priv = self.opts.get(
|
||||||
'ssh_priv',
|
'ssh_priv',
|
||||||
@ -101,7 +101,7 @@ class SSH(object):
|
|||||||
|
|
||||||
def key_deploy(self, host, ret):
|
def key_deploy(self, host, ret):
|
||||||
'''
|
'''
|
||||||
Deploy the ssh key if the minions don't auth
|
Deploy the SSH key if the minions don't auth
|
||||||
'''
|
'''
|
||||||
if not isinstance(ret[host], basestring):
|
if not isinstance(ret[host], basestring):
|
||||||
return ret
|
return ret
|
||||||
@ -405,7 +405,7 @@ class Single():
|
|||||||
class FunctionWrapper(dict):
|
class FunctionWrapper(dict):
|
||||||
'''
|
'''
|
||||||
Create an object that acts like the salt function dict and makes function
|
Create an object that acts like the salt function dict and makes function
|
||||||
calls remotely via the ssh shell system
|
calls remotely via the SSH shell system
|
||||||
'''
|
'''
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@ -440,7 +440,7 @@ class FunctionWrapper(dict):
|
|||||||
|
|
||||||
class SSHState(salt.state.State):
|
class SSHState(salt.state.State):
|
||||||
'''
|
'''
|
||||||
Create a State object which wraps the ssh functions for state operations
|
Create a State object which wraps the SSH functions for state operations
|
||||||
'''
|
'''
|
||||||
def __init__(self, opts, pillar=None, wrapper=None):
|
def __init__(self, opts, pillar=None, wrapper=None):
|
||||||
self.wrapper = wrapper
|
self.wrapper = wrapper
|
||||||
|
@ -1241,7 +1241,7 @@ def recurse(name,
|
|||||||
|
|
||||||
if not _src_path:
|
if not _src_path:
|
||||||
pass
|
pass
|
||||||
elif _src_path.strip('/') not in __salt__['cp.list_master_dirs'](env):
|
elif _src_path.strip('/') not in __salt__['cp.list_master_dirs'](env, _src_path):
|
||||||
ret['result'] = False
|
ret['result'] = False
|
||||||
ret['comment'] = (
|
ret['comment'] = (
|
||||||
'The source: {0} does not exist on the master'.format(source)
|
'The source: {0} does not exist on the master'.format(source)
|
||||||
@ -1353,11 +1353,9 @@ def recurse(name,
|
|||||||
#we're searching for things that start with this *directory*.
|
#we're searching for things that start with this *directory*.
|
||||||
# use '/' since #master only runs on POSIX
|
# use '/' since #master only runs on POSIX
|
||||||
srcpath = srcpath + '/'
|
srcpath = srcpath + '/'
|
||||||
for fn_ in __salt__['cp.list_master'](env):
|
for fn_ in __salt__['cp.list_master'](env, srcpath):
|
||||||
if not fn_.strip():
|
if not fn_.strip():
|
||||||
continue
|
continue
|
||||||
if not fn_.startswith(srcpath):
|
|
||||||
continue
|
|
||||||
|
|
||||||
# fn_ here is the absolute (from file_roots) source path of
|
# fn_ here is the absolute (from file_roots) source path of
|
||||||
# the file to copy from; it is either a normal file or an
|
# the file to copy from; it is either a normal file or an
|
||||||
@ -1393,10 +1391,8 @@ def recurse(name,
|
|||||||
manage_file(dest, src)
|
manage_file(dest, src)
|
||||||
|
|
||||||
if include_empty:
|
if include_empty:
|
||||||
mdirs = __salt__['cp.list_master_dirs'](env)
|
mdirs = __salt__['cp.list_master_dirs'](env, srcpath)
|
||||||
for mdir in mdirs:
|
for mdir in mdirs:
|
||||||
if not mdir.startswith(srcpath):
|
|
||||||
continue
|
|
||||||
if not _check_include_exclude(os.path.relpath(mdir, srcpath),
|
if not _check_include_exclude(os.path.relpath(mdir, srcpath),
|
||||||
include_pat,
|
include_pat,
|
||||||
exclude_pat):
|
exclude_pat):
|
||||||
|
@ -19,6 +19,7 @@ requisite to a pkg.installed state for the package which provides pip
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
# Import python libs
|
# Import python libs
|
||||||
|
import re
|
||||||
import urlparse
|
import urlparse
|
||||||
|
|
||||||
# Import salt libs
|
# Import salt libs
|
||||||
@ -33,6 +34,34 @@ def __virtual__():
|
|||||||
return 'pip' if 'pip.list' in __salt__ else False
|
return 'pip' if 'pip.list' in __salt__ else False
|
||||||
|
|
||||||
|
|
||||||
|
def _find_key(prefix, pip_list):
|
||||||
|
'''
|
||||||
|
Does a case-insensitive match in the pip_list for the desired package.
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
match = next(
|
||||||
|
iter(x for x in pip_list if x.lower() == prefix.lower())
|
||||||
|
)
|
||||||
|
except StopIteration:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return match
|
||||||
|
|
||||||
|
|
||||||
|
def _fulfills_version_spec(version, version_spec):
|
||||||
|
'''
|
||||||
|
Check version number against version specification info and return a
|
||||||
|
boolean value based on whether or not the version number meets the
|
||||||
|
specified version.
|
||||||
|
'''
|
||||||
|
for oper, spec in (version_spec[0:2], version_spec[2:4]):
|
||||||
|
if oper is None:
|
||||||
|
continue
|
||||||
|
if not salt.utils.compare_versions(ver1=version, oper=oper, ver2=spec):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def installed(name,
|
def installed(name,
|
||||||
pip_bin=None,
|
pip_bin=None,
|
||||||
requirements=None,
|
requirements=None,
|
||||||
@ -87,17 +116,38 @@ def installed(name,
|
|||||||
elif env and not bin_env:
|
elif env and not bin_env:
|
||||||
bin_env = env
|
bin_env = env
|
||||||
|
|
||||||
|
ret = {'name': name, 'result': None, 'comment': '', 'changes': {}}
|
||||||
|
|
||||||
scheme, netloc, path, query, fragment = urlparse.urlsplit(name)
|
scheme, netloc, path, query, fragment = urlparse.urlsplit(name)
|
||||||
if scheme and netloc:
|
if scheme and netloc:
|
||||||
# parse as VCS url
|
# parse as VCS url
|
||||||
prefix = path.lstrip('/').split('@', 1)[0]
|
prefix = path.lstrip('/').split('@', 1)[0]
|
||||||
if scheme.startswith("git+"):
|
if scheme.startswith('git+'):
|
||||||
prefix = prefix.rstrip(".git")
|
prefix = prefix.rstrip('.git')
|
||||||
else:
|
else:
|
||||||
# Pull off any requirements specifiers
|
# Split the passed string into the prefix and version
|
||||||
prefix = name.split('=')[0].split('<')[0].split('>')[0].strip()
|
try:
|
||||||
|
version_spec = list(re.match(
|
||||||
|
(r'([^=<>]+)(?:(?:([<>]=?|==?)([^<>=,]+))'
|
||||||
|
r'(?:,([<>]=?|==?)([^<>=]+))?)?$'),
|
||||||
|
name
|
||||||
|
).groups())
|
||||||
|
prefix = version_spec.pop(0)
|
||||||
|
except AttributeError:
|
||||||
|
ret['result'] = False
|
||||||
|
ret['comment'] = 'Invalidly-formatted package {0}'.format(name)
|
||||||
|
return ret
|
||||||
|
else:
|
||||||
|
# Check to see if '=' was used instead of '=='. version_spec will
|
||||||
|
# contain two sets of comparison operators and version numbers, so
|
||||||
|
# we are checking elements 0 and 2 of this list.
|
||||||
|
if any((version_spec[x] == '=' for x in (0, 2))):
|
||||||
|
ret['result'] = False
|
||||||
|
ret['comment'] = ('Invalid version specification in '
|
||||||
|
'package {0}. \'=\' is not supported, use '
|
||||||
|
'\'==\' instead.'.format(name))
|
||||||
|
return ret
|
||||||
|
|
||||||
ret = {'name': name, 'result': None, 'comment': '', 'changes': {}}
|
|
||||||
if runas is not None:
|
if runas is not None:
|
||||||
# The user is using a deprecated argument, warn!
|
# The user is using a deprecated argument, warn!
|
||||||
msg = (
|
msg = (
|
||||||
@ -107,41 +157,48 @@ def installed(name,
|
|||||||
salt.utils.warn_until((0, 18), msg)
|
salt.utils.warn_until((0, 18), msg)
|
||||||
ret.setdefault('warnings', []).append(msg)
|
ret.setdefault('warnings', []).append(msg)
|
||||||
|
|
||||||
# "There can only be one"
|
# "There can only be one"
|
||||||
if runas is not None and user:
|
if user:
|
||||||
raise CommandExecutionError(
|
raise CommandExecutionError(
|
||||||
'The \'runas\' and \'user\' arguments are mutually exclusive. '
|
'The \'runas\' and \'user\' arguments are mutually exclusive. '
|
||||||
'Please use \'user\' as \'runas\' is being deprecated.'
|
'Please use \'user\' as \'runas\' is being deprecated.'
|
||||||
)
|
)
|
||||||
# Support deprecated 'runas' arg
|
# Support deprecated 'runas' arg
|
||||||
elif runas is not None and not user:
|
else:
|
||||||
user = runas
|
user = runas
|
||||||
|
|
||||||
try:
|
try:
|
||||||
pip_list = __salt__['pip.list'](prefix, bin_env, user=user, cwd=cwd)
|
pip_list = __salt__['pip.list'](prefix, bin_env=bin_env,
|
||||||
|
user=user, cwd=cwd)
|
||||||
|
prefix_realname = _find_key(prefix, pip_list)
|
||||||
except (CommandNotFoundError, CommandExecutionError) as err:
|
except (CommandNotFoundError, CommandExecutionError) as err:
|
||||||
ret['result'] = False
|
ret['result'] = False
|
||||||
ret['comment'] = 'Error installing \'{0}\': {1}'.format(name, err)
|
ret['comment'] = 'Error installing \'{0}\': {1}'.format(name, err)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
if ignore_installed is False and prefix.lower() in (p.lower()
|
if ignore_installed is False and prefix_realname is not None:
|
||||||
for p in pip_list):
|
if force_reinstall is False and not upgrade:
|
||||||
if force_reinstall is False and upgrade is False:
|
# Check desired version (if any) against currently-installed
|
||||||
ret['result'] = True
|
if (
|
||||||
ret['comment'] = 'Package already installed'
|
any(version_spec) and
|
||||||
return ret
|
_fulfills_version_spec(pip_list[prefix_realname],
|
||||||
|
version_spec)
|
||||||
|
) or (not any(version_spec)):
|
||||||
|
ret['result'] = True
|
||||||
|
ret['comment'] = ('Python package {0} already '
|
||||||
|
'installed'.format(name))
|
||||||
|
return ret
|
||||||
|
|
||||||
if __opts__['test']:
|
if __opts__['test']:
|
||||||
ret['result'] = None
|
ret['result'] = None
|
||||||
ret['comment'] = 'Python package {0} is set to be installed'.format(
|
ret['comment'] = \
|
||||||
name)
|
'Python package {0} is set to be installed'.format(name)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
# Replace commas (used for version ranges) with semicolons (which are not
|
# Replace commas (used for version ranges) with semicolons (which are not
|
||||||
# supported) in name so it does not treat them as multiple packages. Comma
|
# supported) in name so it does not treat them as multiple packages. Comma
|
||||||
# will be re-added in pip.install call. Wrap in double quotes to allow for
|
# will be re-added in pip.install call.
|
||||||
# version ranges
|
name = name.replace(',', ';')
|
||||||
name = '"' + name.replace(',', ';') + '"'
|
|
||||||
|
|
||||||
if repo:
|
if repo:
|
||||||
name = repo
|
name = repo
|
||||||
@ -153,7 +210,7 @@ def installed(name,
|
|||||||
name = ''
|
name = ''
|
||||||
|
|
||||||
pip_install_call = __salt__['pip.install'](
|
pip_install_call = __salt__['pip.install'](
|
||||||
pkgs=name,
|
pkgs='"{0}"'.format(name),
|
||||||
requirements=requirements,
|
requirements=requirements,
|
||||||
bin_env=bin_env,
|
bin_env=bin_env,
|
||||||
log=log,
|
log=log,
|
||||||
|
@ -48,8 +48,10 @@ if salt.utils.is_windows():
|
|||||||
from salt.modules.win_pkg import _reverse_cmp_pkg_versions
|
from salt.modules.win_pkg import _reverse_cmp_pkg_versions
|
||||||
_get_package_info = namespaced_function(_get_package_info, globals())
|
_get_package_info = namespaced_function(_get_package_info, globals())
|
||||||
get_repo_data = namespaced_function(get_repo_data, globals())
|
get_repo_data = namespaced_function(get_repo_data, globals())
|
||||||
_get_latest_pkg_version = namespaced_function(_get_latest_pkg_version, globals())
|
_get_latest_pkg_version = \
|
||||||
_reverse_cmp_pkg_versions = namespaced_function(_reverse_cmp_pkg_versions, globals())
|
namespaced_function(_get_latest_pkg_version, globals())
|
||||||
|
_reverse_cmp_pkg_versions = \
|
||||||
|
namespaced_function(_reverse_cmp_pkg_versions, globals())
|
||||||
# The following imports are used by the namespaced win_pkg funcs
|
# The following imports are used by the namespaced win_pkg funcs
|
||||||
# and need to be included in their globals.
|
# and need to be included in their globals.
|
||||||
import msgpack
|
import msgpack
|
||||||
@ -65,13 +67,16 @@ def __gen_rtag():
|
|||||||
return os.path.join(__opts__['cachedir'], 'pkg_refresh')
|
return os.path.join(__opts__['cachedir'], 'pkg_refresh')
|
||||||
|
|
||||||
|
|
||||||
def _fulfills_version_spec(versions, oper, desired_version):
|
def _fulfills_version_spec(version, oper, desired_version):
|
||||||
'''
|
'''
|
||||||
Returns True if any of the installed versions match the specified version,
|
Returns True if any of the installed versions match the specified version,
|
||||||
otherwise returns False
|
otherwise returns False
|
||||||
'''
|
'''
|
||||||
for ver in versions:
|
for ver in version:
|
||||||
if __salt__['pkg.compare'](pkg1=ver, oper=oper, pkg2=desired_version):
|
if salt.utils.compare_versions(ver1=version,
|
||||||
|
oper=oper,
|
||||||
|
ver2=desired_version,
|
||||||
|
cmp_func=__salt__.get('version_cmp')):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -153,7 +158,8 @@ def _find_install_targets(name=None, version=None, pkgs=None, sources=None):
|
|||||||
if not cver:
|
if not cver:
|
||||||
targets[pkgname] = pkgver
|
targets[pkgname] = pkgver
|
||||||
continue
|
continue
|
||||||
elif not __salt__['pkg_resource.check_extra_requirements'](pkgname, pkgver):
|
elif not __salt__['pkg_resource.check_extra_requirements'](pkgname,
|
||||||
|
pkgver):
|
||||||
targets[pkgname] = pkgver
|
targets[pkgname] = pkgver
|
||||||
continue
|
continue
|
||||||
# No version specified and pkg is installed, do not add to targets
|
# No version specified and pkg is installed, do not add to targets
|
||||||
@ -170,7 +176,7 @@ def _find_install_targets(name=None, version=None, pkgs=None, sources=None):
|
|||||||
comparison = gt_lt or ''
|
comparison = gt_lt or ''
|
||||||
comparison += eq or ''
|
comparison += eq or ''
|
||||||
# A comparison operator of "=" is redundant, but possible.
|
# A comparison operator of "=" is redundant, but possible.
|
||||||
# Change it to "==" so that it works in pkg.compare.
|
# Change it to "==" so that the version comparison works
|
||||||
if comparison in ['=', '']:
|
if comparison in ['=', '']:
|
||||||
comparison = '=='
|
comparison = '=='
|
||||||
if not _fulfills_version_spec(cver, comparison, verstr):
|
if not _fulfills_version_spec(cver, comparison, verstr):
|
||||||
@ -215,7 +221,7 @@ def _verify_install(desired, new_pkgs):
|
|||||||
comparison = gt_lt or ''
|
comparison = gt_lt or ''
|
||||||
comparison += eq or ''
|
comparison += eq or ''
|
||||||
# A comparison operator of "=" is redundant, but possible.
|
# A comparison operator of "=" is redundant, but possible.
|
||||||
# Change it to "==" so that it works in pkg.compare.
|
# Change it to "==" so that the version comparison works.
|
||||||
if comparison in ('=', ''):
|
if comparison in ('=', ''):
|
||||||
comparison = '=='
|
comparison = '=='
|
||||||
if _fulfills_version_spec(cver, comparison, verstr):
|
if _fulfills_version_spec(cver, comparison, verstr):
|
||||||
@ -557,10 +563,12 @@ def latest(
|
|||||||
msg = 'No information found for "{0}".'.format(pkg)
|
msg = 'No information found for "{0}".'.format(pkg)
|
||||||
log.error(msg)
|
log.error(msg)
|
||||||
problems.append(msg)
|
problems.append(msg)
|
||||||
elif not cur[pkg] or \
|
elif not cur[pkg] \
|
||||||
__salt__['pkg.compare'](pkg1=cur[pkg],
|
or salt.utils.compare_versions(
|
||||||
oper='<',
|
ver1=cur[pkg],
|
||||||
pkg2=avail[pkg]):
|
oper='<',
|
||||||
|
ver2=avail[pkg],
|
||||||
|
cmp_func=__salt__.get('version_cmp')):
|
||||||
targets[pkg] = avail[pkg]
|
targets[pkg] = avail[pkg]
|
||||||
|
|
||||||
if problems:
|
if problems:
|
||||||
@ -608,7 +616,8 @@ def latest(
|
|||||||
|
|
||||||
if changes:
|
if changes:
|
||||||
# Find failed and successful updates
|
# Find failed and successful updates
|
||||||
failed = [x for x in targets if changes[x]['new'] != targets[x]]
|
failed = [x for x in targets
|
||||||
|
if not changes.get(x) or changes[x]['new'] != targets[x]]
|
||||||
successful = [x for x in targets if x not in failed]
|
successful = [x for x in targets if x not in failed]
|
||||||
|
|
||||||
comments = []
|
comments = []
|
||||||
|
@ -5,6 +5,7 @@ from __future__ import absolute_import
|
|||||||
|
|
||||||
# Import python libs
|
# Import python libs
|
||||||
import datetime
|
import datetime
|
||||||
|
import distutils.version # pylint: disable=E0611
|
||||||
import fnmatch
|
import fnmatch
|
||||||
import hashlib
|
import hashlib
|
||||||
import imp
|
import imp
|
||||||
@ -1389,3 +1390,51 @@ def warn_until(version_info,
|
|||||||
|
|
||||||
if _dont_call_warnings is False:
|
if _dont_call_warnings is False:
|
||||||
warnings.warn(message, category, stacklevel=stacklevel)
|
warnings.warn(message, category, stacklevel=stacklevel)
|
||||||
|
|
||||||
|
|
||||||
|
def version_cmp(pkg1, pkg2):
|
||||||
|
'''
|
||||||
|
Compares two version strings using distutils.version.LooseVersion. This is
|
||||||
|
a fallback for providers which don't have a version comparison utility
|
||||||
|
built into them. Return -1 if version1 < version2, 0 if version1 ==
|
||||||
|
version2, and 1 if version1 > version2. Return None if there was a problem
|
||||||
|
making the comparison.
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
if distutils.version.LooseVersion(pkg1) < \
|
||||||
|
distutils.version.LooseVersion(pkg2):
|
||||||
|
return -1
|
||||||
|
elif distutils.version.LooseVersion(pkg1) == \
|
||||||
|
distutils.version.LooseVersion(pkg2):
|
||||||
|
return 0
|
||||||
|
elif distutils.version.LooseVersion(pkg1) > \
|
||||||
|
distutils.version.LooseVersion(pkg2):
|
||||||
|
return 1
|
||||||
|
except Exception as e:
|
||||||
|
log.exception(e)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def compare_versions(ver1='', oper='==', ver2='', cmp_func=None):
|
||||||
|
'''
|
||||||
|
Compares two version numbers. Accepts a custom function to perform the
|
||||||
|
cmp-style version comparison, otherwise uses version_cmp().
|
||||||
|
'''
|
||||||
|
cmp_map = {'<': (-1,), '<=': (-1, 0), '==': (0,),
|
||||||
|
'>=': (0, 1), '>': (1,)}
|
||||||
|
if oper not in ['!='] + cmp_map.keys():
|
||||||
|
log.error('Invalid operator "{0}" for version '
|
||||||
|
'comparison'.format(oper))
|
||||||
|
return False
|
||||||
|
|
||||||
|
if cmp_func is None:
|
||||||
|
cmp_func = version_cmp
|
||||||
|
|
||||||
|
cmp_result = cmp_func(ver1, ver2)
|
||||||
|
if cmp_result is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if oper == '!=':
|
||||||
|
return cmp_result not in cmp_map['==']
|
||||||
|
else:
|
||||||
|
return cmp_result in cmp_map[oper]
|
||||||
|
Loading…
Reference in New Issue
Block a user