Mass nuke deprecated items that are easily removed. ci_complete (#44320)
This commit is contained in:
parent
b7139782cf
commit
617372f8c0
18 changed files with 32 additions and 396 deletions
8
changelogs/fragments/mass-remove-deprecated.yaml
Normal file
8
changelogs/fragments/mass-remove-deprecated.yaml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
minor_changes:
|
||||||
|
- roles - removed deprecated functionality for non YAML role specs (https://github.com/ansible/ansible/pull/44320)
|
||||||
|
- vault - removed deprecated functionality for insecure VaultAES class (https://github.com/ansible/ansible/pull/44320)
|
||||||
|
- gather_subset - removed deprecated functionality for using comma separated list with gather_subset (https://github.com/ansible/ansible/pull/44320)
|
||||||
|
- vars_prompt - removed deprecated functionality supporting 'short form' for vars_prompt (https://github.com/ansible/ansible/pull/44320)
|
||||||
|
- roles - removed deprecated special casing functionality of connection, port, and remote_user for role params (https://github.com/ansible/ansible/pull/44320)
|
||||||
|
- ActionBase - removed deprecated _fixup_perms method (https://github.com/ansible/ansible/pull/44320)
|
||||||
|
- service - removed deprecated state=running (https://github.com/ansible/ansible/pull/44320)
|
|
@ -358,14 +358,7 @@ class GalaxyCLI(CLI):
|
||||||
msg = "Unable to load data from the include requirements file: %s %s"
|
msg = "Unable to load data from the include requirements file: %s %s"
|
||||||
raise AnsibleError(msg % (role_file, e))
|
raise AnsibleError(msg % (role_file, e))
|
||||||
else:
|
else:
|
||||||
display.deprecated("going forward only the yaml format will be supported", version="2.6")
|
raise AnsibleError("Invalid role requirements file")
|
||||||
# roles listed in a file, one per line
|
|
||||||
for rline in f.readlines():
|
|
||||||
if rline.startswith("#") or rline.strip() == '':
|
|
||||||
continue
|
|
||||||
display.debug('found role %s in text file' % str(rline))
|
|
||||||
role = RoleRequirement.role_yaml_parse(rline.strip())
|
|
||||||
roles_left.append(GalaxyRole(self.galaxy, **role))
|
|
||||||
f.close()
|
f.close()
|
||||||
except (IOError, OSError) as e:
|
except (IOError, OSError) as e:
|
||||||
raise AnsibleError('Unable to open %s: %s' % (role_file, str(e)))
|
raise AnsibleError('Unable to open %s: %s' % (role_file, str(e)))
|
||||||
|
|
|
@ -36,7 +36,7 @@ options:
|
||||||
and enabled are required.) Note that reloaded will start the
|
and enabled are required.) Note that reloaded will start the
|
||||||
service if it is not already started, even if your chosen init
|
service if it is not already started, even if your chosen init
|
||||||
system wouldn't normally.
|
system wouldn't normally.
|
||||||
choices: [ reloaded, restarted, running, started, stopped ]
|
choices: [ reloaded, restarted, started, stopped ]
|
||||||
sleep:
|
sleep:
|
||||||
description:
|
description:
|
||||||
- If the service is being C(restarted) then sleep this many seconds
|
- If the service is being C(restarted) then sleep this many seconds
|
||||||
|
@ -49,7 +49,7 @@ options:
|
||||||
- If the service does not respond to the status command, name a
|
- If the service does not respond to the status command, name a
|
||||||
substring to look for as would be found in the output of the I(ps)
|
substring to look for as would be found in the output of the I(ps)
|
||||||
command as a stand-in for a status result. If the string is found,
|
command as a stand-in for a status result. If the string is found,
|
||||||
the service will be assumed to be running.
|
the service will be assumed to be started.
|
||||||
version_added: "0.7"
|
version_added: "0.7"
|
||||||
enabled:
|
enabled:
|
||||||
description:
|
description:
|
||||||
|
@ -75,12 +75,12 @@ notes:
|
||||||
'''
|
'''
|
||||||
|
|
||||||
EXAMPLES = '''
|
EXAMPLES = '''
|
||||||
- name: Start service httpd, if not running
|
- name: Start service httpd, if not started
|
||||||
service:
|
service:
|
||||||
name: httpd
|
name: httpd
|
||||||
state: started
|
state: started
|
||||||
|
|
||||||
- name: Stop service httpd, if running
|
- name: Stop service httpd, if started
|
||||||
service:
|
service:
|
||||||
name: httpd
|
name: httpd
|
||||||
state: stopped
|
state: stopped
|
||||||
|
@ -95,7 +95,7 @@ EXAMPLES = '''
|
||||||
name: httpd
|
name: httpd
|
||||||
state: reloaded
|
state: reloaded
|
||||||
|
|
||||||
- name: Enable service httpd, and not touch the running state
|
- name: Enable service httpd, and not touch the state
|
||||||
service:
|
service:
|
||||||
name: httpd
|
name: httpd
|
||||||
enabled: yes
|
enabled: yes
|
||||||
|
@ -316,7 +316,7 @@ class Service(object):
|
||||||
if self.state and self.running is None:
|
if self.state and self.running is None:
|
||||||
self.module.fail_json(msg="failed determining service state, possible typo of service name?")
|
self.module.fail_json(msg="failed determining service state, possible typo of service name?")
|
||||||
# Find out if state has changed
|
# Find out if state has changed
|
||||||
if not self.running and self.state in ["reloaded", "running", "started"]:
|
if not self.running and self.state in ["reloaded", "started"]:
|
||||||
self.svc_change = True
|
self.svc_change = True
|
||||||
elif self.running and self.state in ["reloaded", "stopped"]:
|
elif self.running and self.state in ["reloaded", "stopped"]:
|
||||||
self.svc_change = True
|
self.svc_change = True
|
||||||
|
@ -330,7 +330,7 @@ class Service(object):
|
||||||
# Only do something if state will change
|
# Only do something if state will change
|
||||||
if self.svc_change:
|
if self.svc_change:
|
||||||
# Control service
|
# Control service
|
||||||
if self.state in ['running', 'started']:
|
if self.state in ['started']:
|
||||||
self.action = "start"
|
self.action = "start"
|
||||||
elif not self.running and self.state == 'reloaded':
|
elif not self.running and self.state == 'reloaded':
|
||||||
self.action = "start"
|
self.action = "start"
|
||||||
|
@ -1518,7 +1518,7 @@ def main():
|
||||||
module = AnsibleModule(
|
module = AnsibleModule(
|
||||||
argument_spec=dict(
|
argument_spec=dict(
|
||||||
name=dict(type='str', required=True),
|
name=dict(type='str', required=True),
|
||||||
state=dict(type='str', choices=['running', 'started', 'stopped', 'reloaded', 'restarted']),
|
state=dict(type='str', choices=['started', 'stopped', 'reloaded', 'restarted']),
|
||||||
sleep=dict(type='int'),
|
sleep=dict(type='int'),
|
||||||
pattern=dict(type='str'),
|
pattern=dict(type='str'),
|
||||||
enabled=dict(type='bool'),
|
enabled=dict(type='bool'),
|
||||||
|
@ -1597,7 +1597,7 @@ def main():
|
||||||
else:
|
else:
|
||||||
# as we may have just bounced the service the service command may not
|
# as we may have just bounced the service the service command may not
|
||||||
# report accurate state at this moment so just show what we ran
|
# report accurate state at this moment so just show what we ran
|
||||||
if service.module.params['state'] in ['reloaded', 'restarted', 'running', 'started']:
|
if service.module.params['state'] in ['reloaded', 'restarted', 'started']:
|
||||||
result['state'] = 'started'
|
result['state'] = 'started'
|
||||||
else:
|
else:
|
||||||
result['state'] = 'stopped'
|
result['state'] = 'stopped'
|
||||||
|
|
|
@ -30,9 +30,6 @@ import warnings
|
||||||
from binascii import hexlify
|
from binascii import hexlify
|
||||||
from binascii import unhexlify
|
from binascii import unhexlify
|
||||||
from binascii import Error as BinasciiError
|
from binascii import Error as BinasciiError
|
||||||
from hashlib import md5
|
|
||||||
from hashlib import sha256
|
|
||||||
from io import BytesIO
|
|
||||||
|
|
||||||
HAS_CRYPTOGRAPHY = False
|
HAS_CRYPTOGRAPHY = False
|
||||||
HAS_PYCRYPTO = False
|
HAS_PYCRYPTO = False
|
||||||
|
@ -1107,146 +1104,6 @@ class VaultEditor:
|
||||||
# CIPHERS #
|
# CIPHERS #
|
||||||
########################################
|
########################################
|
||||||
|
|
||||||
class VaultAES:
|
|
||||||
|
|
||||||
# this version has been obsoleted by the VaultAES256 class
|
|
||||||
# which uses encrypt-then-mac (fixing order) and also improving the KDF used
|
|
||||||
# code remains for upgrade purposes only
|
|
||||||
# http://stackoverflow.com/a/16761459
|
|
||||||
|
|
||||||
# Note: strings in this class should be byte strings by default.
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
if not HAS_CRYPTOGRAPHY and not HAS_PYCRYPTO:
|
|
||||||
raise AnsibleError(NEED_CRYPTO_LIBRARY)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _aes_derive_key_and_iv(b_password, b_salt, key_length, iv_length):
|
|
||||||
|
|
||||||
""" Create a key and an initialization vector """
|
|
||||||
|
|
||||||
b_d = b_di = b''
|
|
||||||
while len(b_d) < key_length + iv_length:
|
|
||||||
b_text = b''.join([b_di, b_password, b_salt])
|
|
||||||
b_di = to_bytes(md5(b_text).digest(), errors='strict')
|
|
||||||
b_d += b_di
|
|
||||||
|
|
||||||
b_key = b_d[:key_length]
|
|
||||||
b_iv = b_d[key_length:key_length + iv_length]
|
|
||||||
|
|
||||||
return b_key, b_iv
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def encrypt(b_plaintext, b_password, key_length=32):
|
|
||||||
|
|
||||||
""" Read plaintext data from in_file and write encrypted to out_file """
|
|
||||||
|
|
||||||
raise AnsibleError("Encryption disabled for deprecated VaultAES class")
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _parse_plaintext_envelope(b_envelope):
|
|
||||||
# split out sha and verify decryption
|
|
||||||
b_split_data = b_envelope.split(b"\n", 1)
|
|
||||||
b_this_sha = b_split_data[0]
|
|
||||||
b_plaintext = b_split_data[1]
|
|
||||||
b_test_sha = to_bytes(sha256(b_plaintext).hexdigest())
|
|
||||||
|
|
||||||
return b_plaintext, b_this_sha, b_test_sha
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _decrypt_cryptography(cls, b_salt, b_ciphertext, b_password, key_length):
|
|
||||||
|
|
||||||
bs = algorithms.AES.block_size // 8
|
|
||||||
b_key, b_iv = cls._aes_derive_key_and_iv(b_password, b_salt, key_length, bs)
|
|
||||||
cipher = C_Cipher(algorithms.AES(b_key), modes.CBC(b_iv), CRYPTOGRAPHY_BACKEND).decryptor()
|
|
||||||
unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
|
|
||||||
|
|
||||||
try:
|
|
||||||
b_plaintext_envelope = unpadder.update(
|
|
||||||
cipher.update(b_ciphertext) + cipher.finalize()
|
|
||||||
) + unpadder.finalize()
|
|
||||||
except ValueError:
|
|
||||||
# In VaultAES, ValueError: invalid padding bytes can mean bad
|
|
||||||
# password was given
|
|
||||||
raise AnsibleError("Decryption failed")
|
|
||||||
|
|
||||||
b_plaintext, b_this_sha, b_test_sha = cls._parse_plaintext_envelope(b_plaintext_envelope)
|
|
||||||
|
|
||||||
if b_this_sha != b_test_sha:
|
|
||||||
raise AnsibleError("Decryption failed")
|
|
||||||
|
|
||||||
return b_plaintext
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _decrypt_pycrypto(cls, b_salt, b_ciphertext, b_password, key_length):
|
|
||||||
in_file = BytesIO(b_ciphertext)
|
|
||||||
in_file.seek(0)
|
|
||||||
out_file = BytesIO()
|
|
||||||
|
|
||||||
bs = AES_pycrypto.block_size
|
|
||||||
|
|
||||||
b_key, b_iv = cls._aes_derive_key_and_iv(b_password, b_salt, key_length, bs)
|
|
||||||
cipher = AES_pycrypto.new(b_key, AES_pycrypto.MODE_CBC, b_iv)
|
|
||||||
b_next_chunk = b''
|
|
||||||
finished = False
|
|
||||||
|
|
||||||
while not finished:
|
|
||||||
b_chunk, b_next_chunk = b_next_chunk, cipher.decrypt(in_file.read(1024 * bs))
|
|
||||||
if len(b_next_chunk) == 0:
|
|
||||||
if PY3:
|
|
||||||
padding_length = b_chunk[-1]
|
|
||||||
else:
|
|
||||||
padding_length = ord(b_chunk[-1])
|
|
||||||
|
|
||||||
b_chunk = b_chunk[:-padding_length]
|
|
||||||
finished = True
|
|
||||||
|
|
||||||
out_file.write(b_chunk)
|
|
||||||
out_file.flush()
|
|
||||||
|
|
||||||
# reset the stream pointer to the beginning
|
|
||||||
out_file.seek(0)
|
|
||||||
b_plaintext_envelope = out_file.read()
|
|
||||||
out_file.close()
|
|
||||||
|
|
||||||
b_plaintext, b_this_sha, b_test_sha = cls._parse_plaintext_envelope(b_plaintext_envelope)
|
|
||||||
|
|
||||||
if b_this_sha != b_test_sha:
|
|
||||||
raise AnsibleError("Decryption failed")
|
|
||||||
|
|
||||||
return b_plaintext
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def decrypt(cls, b_vaulttext, secret, key_length=32):
|
|
||||||
|
|
||||||
""" Decrypt the given data and return it
|
|
||||||
:arg b_data: A byte string containing the encrypted data
|
|
||||||
:arg b_password: A byte string containing the encryption password
|
|
||||||
:arg key_length: Length of the key
|
|
||||||
:returns: A byte string containing the decrypted data
|
|
||||||
"""
|
|
||||||
|
|
||||||
display.deprecated(u'The VaultAES format is insecure and has been '
|
|
||||||
'deprecated since Ansible-1.5. Use vault rekey FILENAME to '
|
|
||||||
'switch to the newer VaultAES256 format', version='2.3')
|
|
||||||
# http://stackoverflow.com/a/14989032
|
|
||||||
|
|
||||||
b_vaultdata = _unhexlify(b_vaulttext)
|
|
||||||
b_salt = b_vaultdata[len(b'Salted__'):16]
|
|
||||||
b_ciphertext = b_vaultdata[16:]
|
|
||||||
|
|
||||||
b_password = secret.bytes
|
|
||||||
|
|
||||||
if HAS_CRYPTOGRAPHY:
|
|
||||||
b_plaintext = cls._decrypt_cryptography(b_salt, b_ciphertext, b_password, key_length)
|
|
||||||
elif HAS_PYCRYPTO:
|
|
||||||
b_plaintext = cls._decrypt_pycrypto(b_salt, b_ciphertext, b_password, key_length)
|
|
||||||
else:
|
|
||||||
raise AnsibleError(NEED_CRYPTO_LIBRARY + ' (Late detection)')
|
|
||||||
|
|
||||||
return b_plaintext
|
|
||||||
|
|
||||||
|
|
||||||
class VaultAES256:
|
class VaultAES256:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -1470,6 +1327,5 @@ class VaultAES256:
|
||||||
# Keys could be made bytes later if the code that gets the data is more
|
# Keys could be made bytes later if the code that gets the data is more
|
||||||
# naturally byte-oriented
|
# naturally byte-oriented
|
||||||
CIPHER_MAPPING = {
|
CIPHER_MAPPING = {
|
||||||
u'AES': VaultAES,
|
|
||||||
u'AES256': VaultAES256,
|
u'AES256': VaultAES256,
|
||||||
}
|
}
|
||||||
|
|
|
@ -382,17 +382,10 @@ class FieldAttributeBase(with_metaclass(BaseMeta, object)):
|
||||||
if isinstance(value, string_types) and '%' in value:
|
if isinstance(value, string_types) and '%' in value:
|
||||||
value = value.replace('%', '')
|
value = value.replace('%', '')
|
||||||
value = float(value)
|
value = float(value)
|
||||||
elif attribute.isa in ('list', 'barelist'):
|
elif attribute.isa == 'list':
|
||||||
if value is None:
|
if value is None:
|
||||||
value = []
|
value = []
|
||||||
elif not isinstance(value, list):
|
elif not isinstance(value, list):
|
||||||
if isinstance(value, string_types) and attribute.isa == 'barelist':
|
|
||||||
display.deprecated(
|
|
||||||
"Using comma separated values for a list has been deprecated. "
|
|
||||||
"You should instead use the correct YAML syntax for lists. "
|
|
||||||
)
|
|
||||||
value = value.split(',')
|
|
||||||
else:
|
|
||||||
value = [value]
|
value = [value]
|
||||||
if attribute.listof is not None:
|
if attribute.listof is not None:
|
||||||
for item in value:
|
for item in value:
|
||||||
|
|
|
@ -59,7 +59,7 @@ class Play(Base, Taggable, Become):
|
||||||
# Facts
|
# Facts
|
||||||
_fact_path = FieldAttribute(isa='string', default=None)
|
_fact_path = FieldAttribute(isa='string', default=None)
|
||||||
_gather_facts = FieldAttribute(isa='bool', default=None, always_post_validate=True)
|
_gather_facts = FieldAttribute(isa='bool', default=None, always_post_validate=True)
|
||||||
_gather_subset = FieldAttribute(isa='barelist', default=None, always_post_validate=True)
|
_gather_subset = FieldAttribute(isa='list', default=None, always_post_validate=True)
|
||||||
_gather_timeout = FieldAttribute(isa='int', default=None, always_post_validate=True)
|
_gather_timeout = FieldAttribute(isa='int', default=None, always_post_validate=True)
|
||||||
|
|
||||||
# Variable Attributes
|
# Variable Attributes
|
||||||
|
@ -203,18 +203,7 @@ class Play(Base, Taggable, Become):
|
||||||
if new_ds is not None:
|
if new_ds is not None:
|
||||||
for prompt_data in new_ds:
|
for prompt_data in new_ds:
|
||||||
if 'name' not in prompt_data:
|
if 'name' not in prompt_data:
|
||||||
display.deprecated("Using the 'short form' for vars_prompt has been deprecated", version="2.7")
|
raise AnsibleParserError("Invalid vars_prompt data structure", obj=ds)
|
||||||
for vname, prompt in prompt_data.items():
|
|
||||||
vars_prompts.append(dict(
|
|
||||||
name=vname,
|
|
||||||
prompt=prompt,
|
|
||||||
default=None,
|
|
||||||
private=None,
|
|
||||||
confirm=None,
|
|
||||||
encrypt=None,
|
|
||||||
salt_size=None,
|
|
||||||
salt=None,
|
|
||||||
))
|
|
||||||
else:
|
else:
|
||||||
vars_prompts.append(prompt_data)
|
vars_prompts.append(prompt_data)
|
||||||
return vars_prompts
|
return vars_prompts
|
||||||
|
|
|
@ -204,12 +204,7 @@ class RoleDefinition(Base, Become, Conditional, Taggable):
|
||||||
# other mechanism where we exclude certain kinds of field attributes,
|
# other mechanism where we exclude certain kinds of field attributes,
|
||||||
# or make this list more automatic in some way so we don't have to
|
# or make this list more automatic in some way so we don't have to
|
||||||
# remember to update it manually.
|
# remember to update it manually.
|
||||||
if key not in base_attribute_names or key in ('connection', 'port', 'remote_user'):
|
if key not in base_attribute_names:
|
||||||
if key in ('connection', 'port', 'remote_user'):
|
|
||||||
display.deprecated("Using '%s' as a role param has been deprecated. " % key +
|
|
||||||
"In the future, these values should be entered in the `vars:` " +
|
|
||||||
"section for roles, but for now we'll store it as both a param and an attribute.", version="2.7")
|
|
||||||
role_def[key] = value
|
|
||||||
# this key does not match a field attribute, so it must be a role param
|
# this key does not match a field attribute, so it must be a role param
|
||||||
role_params[key] = value
|
role_params[key] = value
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -53,7 +53,7 @@ class RoleInclude(RoleDefinition):
|
||||||
raise AnsibleParserError("Invalid role definition: %s" % to_native(data))
|
raise AnsibleParserError("Invalid role definition: %s" % to_native(data))
|
||||||
|
|
||||||
if isinstance(data, string_types) and ',' in data:
|
if isinstance(data, string_types) and ',' in data:
|
||||||
data = RoleRequirement.role_spec_parse(data)
|
raise AnsibleError("Invalid old style role requirement: %s" % data)
|
||||||
|
|
||||||
ri = RoleInclude(play=play, role_basedir=current_role_path, variable_manager=variable_manager, loader=loader)
|
ri = RoleInclude(play=play, role_basedir=current_role_path, variable_manager=variable_manager, loader=loader)
|
||||||
return ri.load_data(data, variable_manager=variable_manager, loader=loader)
|
return ri.load_data(data, variable_manager=variable_manager, loader=loader)
|
||||||
|
|
|
@ -77,53 +77,6 @@ class RoleRequirement(RoleDefinition):
|
||||||
trailing_path = trailing_path.split(',')[0]
|
trailing_path = trailing_path.split(',')[0]
|
||||||
return trailing_path
|
return trailing_path
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def role_spec_parse(role_spec):
|
|
||||||
# takes a repo and a version like
|
|
||||||
# git+http://git.example.com/repos/repo.git,v1.0
|
|
||||||
# and returns a list of properties such as:
|
|
||||||
# {
|
|
||||||
# 'scm': 'git',
|
|
||||||
# 'src': 'http://git.example.com/repos/repo.git',
|
|
||||||
# 'version': 'v1.0',
|
|
||||||
# 'name': 'repo'
|
|
||||||
# }
|
|
||||||
display.deprecated("The comma separated role spec format, use the yaml/explicit format instead. Line that trigger this: %s" % role_spec,
|
|
||||||
version="2.7")
|
|
||||||
|
|
||||||
default_role_versions = dict(git='master', hg='tip')
|
|
||||||
|
|
||||||
role_spec = role_spec.strip()
|
|
||||||
role_version = ''
|
|
||||||
if role_spec == "" or role_spec.startswith("#"):
|
|
||||||
return (None, None, None, None)
|
|
||||||
|
|
||||||
tokens = [s.strip() for s in role_spec.split(',')]
|
|
||||||
|
|
||||||
# assume https://github.com URLs are git+https:// URLs and not
|
|
||||||
# tarballs unless they end in '.zip'
|
|
||||||
if 'github.com/' in tokens[0] and not tokens[0].startswith("git+") and not tokens[0].endswith('.tar.gz'):
|
|
||||||
tokens[0] = 'git+' + tokens[0]
|
|
||||||
|
|
||||||
if '+' in tokens[0]:
|
|
||||||
(scm, role_url) = tokens[0].split('+')
|
|
||||||
else:
|
|
||||||
scm = None
|
|
||||||
role_url = tokens[0]
|
|
||||||
|
|
||||||
if len(tokens) >= 2:
|
|
||||||
role_version = tokens[1]
|
|
||||||
|
|
||||||
if len(tokens) == 3:
|
|
||||||
role_name = tokens[2]
|
|
||||||
else:
|
|
||||||
role_name = RoleRequirement.repo_url_to_role_name(tokens[0])
|
|
||||||
|
|
||||||
if scm and not role_version:
|
|
||||||
role_version = default_role_versions.get(scm, '')
|
|
||||||
|
|
||||||
return dict(scm=scm, src=role_url, version=role_version, name=role_name)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def role_yaml_parse(role):
|
def role_yaml_parse(role):
|
||||||
|
|
||||||
|
@ -152,8 +105,7 @@ class RoleRequirement(RoleDefinition):
|
||||||
if 'role' in role:
|
if 'role' in role:
|
||||||
name = role['role']
|
name = role['role']
|
||||||
if ',' in name:
|
if ',' in name:
|
||||||
# Old style: {role: "galaxy.role,version,name", other_vars: "here" }
|
raise AnsibleError("Invalid old style role requirement: %s" % name)
|
||||||
role = RoleRequirement.role_spec_parse(role['role'])
|
|
||||||
else:
|
else:
|
||||||
del role['role']
|
del role['role']
|
||||||
role['name'] = name
|
role['name'] = name
|
||||||
|
|
|
@ -377,30 +377,6 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
||||||
|
|
||||||
return remote_path
|
return remote_path
|
||||||
|
|
||||||
def _fixup_perms(self, remote_path, remote_user=None, execute=True, recursive=True):
|
|
||||||
"""
|
|
||||||
We need the files we upload to be readable (and sometimes executable)
|
|
||||||
by the user being sudo'd to but we want to limit other people's access
|
|
||||||
(because the files could contain passwords or other private
|
|
||||||
information.
|
|
||||||
|
|
||||||
Deprecated in favor of _fixup_perms2. Ansible code has been updated to
|
|
||||||
use _fixup_perms2. This code is maintained to provide partial support
|
|
||||||
for custom actions (non-recursive mode only).
|
|
||||||
|
|
||||||
"""
|
|
||||||
if remote_user is None:
|
|
||||||
remote_user = self._play_context.remote_user
|
|
||||||
|
|
||||||
display.deprecated('_fixup_perms is deprecated. Use _fixup_perms2 instead.', version='2.4', removed=False)
|
|
||||||
|
|
||||||
if recursive:
|
|
||||||
raise AnsibleError('_fixup_perms with recursive=True (the default) is no longer supported. ' +
|
|
||||||
'Use _fixup_perms2 if support for previous releases is not required. '
|
|
||||||
'Otherwise use fixup_perms with recursive=False.')
|
|
||||||
|
|
||||||
return self._fixup_perms2([remote_path], remote_user, execute)
|
|
||||||
|
|
||||||
def _fixup_perms2(self, remote_paths, remote_user=None, execute=True):
|
def _fixup_perms2(self, remote_paths, remote_user=None, execute=True):
|
||||||
"""
|
"""
|
||||||
We need the files we upload to be readable (and sometimes executable)
|
We need the files we upload to be readable (and sometimes executable)
|
||||||
|
|
|
@ -65,11 +65,6 @@ class ActionModule(ActionBase):
|
||||||
if 'use' in new_module_args:
|
if 'use' in new_module_args:
|
||||||
del new_module_args['use']
|
del new_module_args['use']
|
||||||
|
|
||||||
# for backwards compatibility
|
|
||||||
if 'state' in new_module_args and new_module_args['state'] == 'running':
|
|
||||||
self._display.deprecated(msg="state=running is deprecated. Please use state=started", version="2.7")
|
|
||||||
new_module_args['state'] = 'started'
|
|
||||||
|
|
||||||
if module in self.UNUSED_PARAMS:
|
if module in self.UNUSED_PARAMS:
|
||||||
for unused in self.UNUSED_PARAMS[module]:
|
for unused in self.UNUSED_PARAMS[module]:
|
||||||
if unused in new_module_args:
|
if unused in new_module_args:
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
hosts: facthost21
|
hosts: facthost21
|
||||||
tags: [ 'fact_network' ]
|
tags: [ 'fact_network' ]
|
||||||
connection: local
|
connection: local
|
||||||
gather_subset: "!all,network"
|
gather_subset: ["!all", "network"]
|
||||||
gather_facts: yes
|
gather_facts: yes
|
||||||
tasks:
|
tasks:
|
||||||
- name: Test that retrieving network facts works and gets prereqs from platform and distribution
|
- name: Test that retrieving network facts works and gets prereqs from platform and distribution
|
||||||
|
@ -69,7 +69,7 @@
|
||||||
hosts: facthost23
|
hosts: facthost23
|
||||||
tags: [ 'fact_service_mgr' ]
|
tags: [ 'fact_service_mgr' ]
|
||||||
connection: local
|
connection: local
|
||||||
gather_subset: "!all,service_mgr"
|
gather_subset: ["!all", "service_mgr"]
|
||||||
gather_facts: yes
|
gather_facts: yes
|
||||||
tasks:
|
tasks:
|
||||||
- name: Test that retrieving service_mgr facts works and gets prereqs from platform and distribution
|
- name: Test that retrieving service_mgr facts works and gets prereqs from platform and distribution
|
||||||
|
@ -195,7 +195,7 @@
|
||||||
- hosts: facthost2
|
- hosts: facthost2
|
||||||
tags: [ 'fact_network' ]
|
tags: [ 'fact_network' ]
|
||||||
connection: local
|
connection: local
|
||||||
gather_subset: "!all,!min,network"
|
gather_subset: ["!all", "!min", "network"]
|
||||||
gather_facts: yes
|
gather_facts: yes
|
||||||
tasks:
|
tasks:
|
||||||
- name: Test that retrieving network facts work
|
- name: Test that retrieving network facts work
|
||||||
|
@ -237,7 +237,7 @@
|
||||||
- hosts: facthost5
|
- hosts: facthost5
|
||||||
tags: [ 'fact_comma_string' ]
|
tags: [ 'fact_comma_string' ]
|
||||||
connection: local
|
connection: local
|
||||||
gather_subset: "virtual,network"
|
gather_subset: ["virtual", "network"]
|
||||||
gather_facts: yes
|
gather_facts: yes
|
||||||
tasks:
|
tasks:
|
||||||
- name: Test that retrieving virtualization and network as a string works
|
- name: Test that retrieving virtualization and network as a string works
|
||||||
|
@ -288,7 +288,7 @@
|
||||||
- hosts: facthost8
|
- hosts: facthost8
|
||||||
tags: [ 'fact_mixed_negation_addition' ]
|
tags: [ 'fact_mixed_negation_addition' ]
|
||||||
connection: local
|
connection: local
|
||||||
gather_subset: "!hardware,network"
|
gather_subset: ["!hardware", "network"]
|
||||||
gather_facts: yes
|
gather_facts: yes
|
||||||
tasks:
|
tasks:
|
||||||
- name: Test that negation and additional subsets work together
|
- name: Test that negation and additional subsets work together
|
||||||
|
@ -302,7 +302,7 @@
|
||||||
- hosts: facthost14
|
- hosts: facthost14
|
||||||
tags: [ 'fact_mixed_negation_addition_min' ]
|
tags: [ 'fact_mixed_negation_addition_min' ]
|
||||||
connection: local
|
connection: local
|
||||||
gather_subset: "!all,!min,network"
|
gather_subset: ["!all", "!min", "network"]
|
||||||
gather_facts: yes
|
gather_facts: yes
|
||||||
tasks:
|
tasks:
|
||||||
- name: Test that negation and additional subsets work together for min subset
|
- name: Test that negation and additional subsets work together for min subset
|
||||||
|
@ -319,7 +319,7 @@
|
||||||
- hosts: facthost15
|
- hosts: facthost15
|
||||||
tags: [ 'fact_negate_all_min_add_pkg_mgr' ]
|
tags: [ 'fact_negate_all_min_add_pkg_mgr' ]
|
||||||
connection: local
|
connection: local
|
||||||
gather_subset: "!all,!min,pkg_mgr"
|
gather_subset: ["!all", "!min", "pkg_mgr"]
|
||||||
gather_facts: yes
|
gather_facts: yes
|
||||||
tasks:
|
tasks:
|
||||||
- name: Test that negation and additional subsets work together for min subset
|
- name: Test that negation and additional subsets work together for min subset
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
$ANSIBLE_VAULT;1.0;AES
|
|
||||||
53616c7465645f5fd0026926a2d415a28a2622116273fbc90e377225c12a347e1daf4456d36a77f9
|
|
||||||
9ad98d59f61d06a4b66718d855f16fb7bdfe54d1ec8aeaa4d06c2dc1fa630ae1846a029877f0eeb1
|
|
||||||
83c62ffb04c2512995e815de4b4d29ed
|
|
|
@ -1,4 +0,0 @@
|
||||||
$ANSIBLE_VAULT;1.1;AES
|
|
||||||
53616c7465645f5fc107ce1ef4d7b455e038a13b053225776458052f8f8f332d554809d3f150bfa3
|
|
||||||
fe3db930508b65e0ff5947e4386b79af8ab094017629590ef6ba486814cf70f8e4ab0ed0c7d2587e
|
|
||||||
786a5a15efeb787e1958cbdd480d076c
|
|
|
@ -106,23 +106,6 @@ if [ -x "$(command -v setsid)" ]; then
|
||||||
cat log
|
cat log
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# old format
|
|
||||||
ansible-vault view "$@" --vault-password-file vault-password-ansible format_1_0_AES.yml
|
|
||||||
|
|
||||||
ansible-vault view "$@" --vault-password-file vault-password-ansible format_1_1_AES.yml
|
|
||||||
|
|
||||||
# old format, wrong password
|
|
||||||
echo "The wrong password tests are expected to return 1"
|
|
||||||
ansible-vault view "$@" --vault-password-file vault-password-wrong format_1_0_AES.yml && :
|
|
||||||
WRONG_RC=$?
|
|
||||||
echo "rc was $WRONG_RC (1 is expected)"
|
|
||||||
[ $WRONG_RC -eq 1 ]
|
|
||||||
|
|
||||||
ansible-vault view "$@" --vault-password-file vault-password-wrong format_1_1_AES.yml && :
|
|
||||||
WRONG_RC=$?
|
|
||||||
echo "rc was $WRONG_RC (1 is expected)"
|
|
||||||
[ $WRONG_RC -eq 1 ]
|
|
||||||
|
|
||||||
ansible-vault view "$@" --vault-password-file vault-password-wrong format_1_1_AES256.yml && :
|
ansible-vault view "$@" --vault-password-file vault-password-wrong format_1_1_AES256.yml && :
|
||||||
WRONG_RC=$?
|
WRONG_RC=$?
|
||||||
echo "rc was $WRONG_RC (1 is expected)"
|
echo "rc was $WRONG_RC (1 is expected)"
|
||||||
|
|
|
@ -751,20 +751,6 @@ class TestVaultLib(unittest.TestCase):
|
||||||
self.assertEqual(cipher_name, u'TEST', msg="cipher name was not properly set")
|
self.assertEqual(cipher_name, u'TEST', msg="cipher name was not properly set")
|
||||||
self.assertEqual(b_version, b"9.9", msg="version was not properly set")
|
self.assertEqual(b_version, b"9.9", msg="version was not properly set")
|
||||||
|
|
||||||
def test_encrypt_decrypt_aes(self):
|
|
||||||
self.v.cipher_name = u'AES'
|
|
||||||
vault_secrets = self._vault_secrets_from_password('default', 'ansible')
|
|
||||||
self.v.secrets = vault_secrets
|
|
||||||
# AES encryption code has been removed, so this is old output for
|
|
||||||
# AES-encrypted 'foobar' with password 'ansible'.
|
|
||||||
b_vaulttext = b'''$ANSIBLE_VAULT;1.1;AES
|
|
||||||
53616c7465645f5fc107ce1ef4d7b455e038a13b053225776458052f8f8f332d554809d3f150bfa3
|
|
||||||
fe3db930508b65e0ff5947e4386b79af8ab094017629590ef6ba486814cf70f8e4ab0ed0c7d2587e
|
|
||||||
786a5a15efeb787e1958cbdd480d076c
|
|
||||||
'''
|
|
||||||
b_plaintext = self.v.decrypt(b_vaulttext)
|
|
||||||
self.assertEqual(b_plaintext, b"foobar", msg="decryption failed")
|
|
||||||
|
|
||||||
def test_encrypt_decrypt_aes256(self):
|
def test_encrypt_decrypt_aes256(self):
|
||||||
self.v.cipher_name = u'AES256'
|
self.v.cipher_name = u'AES256'
|
||||||
plaintext = u"foobar"
|
plaintext = u"foobar"
|
||||||
|
@ -929,13 +915,6 @@ fe3db930508b65e0ff5947e4386b79af8ab094017629590ef6ba486814cf70f8e4ab0ed0c7d2587e
|
||||||
self.assertEqual('ansible_devel', vault_id)
|
self.assertEqual('ansible_devel', vault_id)
|
||||||
self.assertEqual(b'1.2', b_version)
|
self.assertEqual(b'1.2', b_version)
|
||||||
|
|
||||||
def test_encrypt_encrypted(self):
|
|
||||||
self.v.cipher_name = u'AES'
|
|
||||||
b_vaulttext = b"$ANSIBLE_VAULT;9.9;TEST\n%s" % hexlify(b"ansible")
|
|
||||||
vaulttext = to_text(b_vaulttext, errors='strict')
|
|
||||||
self.assertRaises(errors.AnsibleError, self.v.encrypt, b_vaulttext)
|
|
||||||
self.assertRaises(errors.AnsibleError, self.v.encrypt, vaulttext)
|
|
||||||
|
|
||||||
def test_decrypt_decrypted(self):
|
def test_decrypt_decrypted(self):
|
||||||
plaintext = u"ansible"
|
plaintext = u"ansible"
|
||||||
self.assertRaises(errors.AnsibleError, self.v.decrypt, plaintext)
|
self.assertRaises(errors.AnsibleError, self.v.decrypt, plaintext)
|
||||||
|
|
|
@ -36,11 +36,6 @@ from ansible.module_utils._text import to_bytes, to_text
|
||||||
|
|
||||||
from units.mock.vault_helper import TextVaultSecret
|
from units.mock.vault_helper import TextVaultSecret
|
||||||
|
|
||||||
v10_data = """$ANSIBLE_VAULT;1.0;AES
|
|
||||||
53616c7465645f5fd0026926a2d415a28a2622116273fbc90e377225c12a347e1daf4456d36a77f9
|
|
||||||
9ad98d59f61d06a4b66718d855f16fb7bdfe54d1ec8aeaa4d06c2dc1fa630ae1846a029877f0eeb1
|
|
||||||
83c62ffb04c2512995e815de4b4d29ed"""
|
|
||||||
|
|
||||||
v11_data = """$ANSIBLE_VAULT;1.1;AES256
|
v11_data = """$ANSIBLE_VAULT;1.1;AES256
|
||||||
62303130653266653331306264616235333735323636616539316433666463323964623162386137
|
62303130653266653331306264616235333735323636616539316433666463323964623162386137
|
||||||
3961616263373033353631316333623566303532663065310a393036623466376263393961326530
|
3961616263373033353631316333623566303532663065310a393036623466376263393961326530
|
||||||
|
@ -458,33 +453,6 @@ class TestVaultEditor(unittest.TestCase):
|
||||||
|
|
||||||
self.assertTrue(os.path.exists(tmp_file.name))
|
self.assertTrue(os.path.exists(tmp_file.name))
|
||||||
|
|
||||||
def test_decrypt_1_0(self):
|
|
||||||
# Skip testing decrypting 1.0 files if we don't have access to AES, KDF or Counter.
|
|
||||||
v10_file = tempfile.NamedTemporaryFile(delete=False)
|
|
||||||
with v10_file as f:
|
|
||||||
f.write(to_bytes(v10_data))
|
|
||||||
|
|
||||||
ve = self._vault_editor(self._secrets("ansible"))
|
|
||||||
|
|
||||||
# make sure the password functions for the cipher
|
|
||||||
error_hit = False
|
|
||||||
try:
|
|
||||||
ve.decrypt_file(v10_file.name)
|
|
||||||
except errors.AnsibleError:
|
|
||||||
error_hit = True
|
|
||||||
raise
|
|
||||||
|
|
||||||
# verify decrypted content
|
|
||||||
f = open(v10_file.name, "rb")
|
|
||||||
fdata = to_text(f.read())
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
os.unlink(v10_file.name)
|
|
||||||
|
|
||||||
assert error_hit is False, "error decrypting 1.0 file"
|
|
||||||
self.assertEqual(fdata.strip(), "foo")
|
|
||||||
assert fdata.strip() == "foo", "incorrect decryption of 1.0 file: %s" % fdata.strip()
|
|
||||||
|
|
||||||
def test_decrypt_1_1(self):
|
def test_decrypt_1_1(self):
|
||||||
v11_file = tempfile.NamedTemporaryFile(delete=False)
|
v11_file = tempfile.NamedTemporaryFile(delete=False)
|
||||||
with v11_file as f:
|
with v11_file as f:
|
||||||
|
@ -509,43 +477,6 @@ class TestVaultEditor(unittest.TestCase):
|
||||||
assert error_hit is False, "error decrypting 1.1 file"
|
assert error_hit is False, "error decrypting 1.1 file"
|
||||||
assert fdata.strip() == "foo", "incorrect decryption of 1.1 file: %s" % fdata.strip()
|
assert fdata.strip() == "foo", "incorrect decryption of 1.1 file: %s" % fdata.strip()
|
||||||
|
|
||||||
def test_rekey_migration(self):
|
|
||||||
v10_file = tempfile.NamedTemporaryFile(delete=False)
|
|
||||||
with v10_file as f:
|
|
||||||
f.write(to_bytes(v10_data))
|
|
||||||
|
|
||||||
ve = self._vault_editor(self._secrets("ansible"))
|
|
||||||
|
|
||||||
# make sure the password functions for the cipher
|
|
||||||
error_hit = False
|
|
||||||
new_secrets = self._secrets("ansible2")
|
|
||||||
try:
|
|
||||||
ve.rekey_file(v10_file.name, vault.match_encrypt_secret(new_secrets)[1])
|
|
||||||
except errors.AnsibleError:
|
|
||||||
error_hit = True
|
|
||||||
|
|
||||||
# verify decrypted content
|
|
||||||
f = open(v10_file.name, "rb")
|
|
||||||
fdata = f.read()
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
assert error_hit is False, "error rekeying 1.0 file to 1.1"
|
|
||||||
|
|
||||||
# ensure filedata can be decrypted, is 1.1 and is AES256
|
|
||||||
vl = VaultLib(new_secrets)
|
|
||||||
dec_data = None
|
|
||||||
error_hit = False
|
|
||||||
try:
|
|
||||||
dec_data = vl.decrypt(fdata)
|
|
||||||
except errors.AnsibleError:
|
|
||||||
error_hit = True
|
|
||||||
|
|
||||||
os.unlink(v10_file.name)
|
|
||||||
|
|
||||||
self.assertIn(b'AES256', fdata, 'AES256 was not found in vault file %s' % to_text(fdata))
|
|
||||||
assert error_hit is False, "error decrypting migrated 1.0 file"
|
|
||||||
assert dec_data.strip() == b"foo", "incorrect decryption of rekeyed/migrated file: %s" % dec_data
|
|
||||||
|
|
||||||
def test_real_path_dash(self):
|
def test_real_path_dash(self):
|
||||||
filename = '-'
|
filename = '-'
|
||||||
ve = self._vault_editor()
|
ve = self._vault_editor()
|
||||||
|
|
|
@ -348,7 +348,6 @@ class BaseSubClass(base.Base):
|
||||||
_test_attr_list_no_listof = FieldAttribute(isa='list', always_post_validate=True)
|
_test_attr_list_no_listof = FieldAttribute(isa='list', always_post_validate=True)
|
||||||
_test_attr_list_required = FieldAttribute(isa='list', listof=string_types, required=True,
|
_test_attr_list_required = FieldAttribute(isa='list', listof=string_types, required=True,
|
||||||
default=[], always_post_validate=True)
|
default=[], always_post_validate=True)
|
||||||
_test_attr_barelist = FieldAttribute(isa='barelist', always_post_validate=True)
|
|
||||||
_test_attr_string = FieldAttribute(isa='string', default='the_test_attr_string_default_value')
|
_test_attr_string = FieldAttribute(isa='string', default='the_test_attr_string_default_value')
|
||||||
_test_attr_string_required = FieldAttribute(isa='string', required=True,
|
_test_attr_string_required = FieldAttribute(isa='string', required=True,
|
||||||
default='the_test_attr_string_default_value')
|
default='the_test_attr_string_default_value')
|
||||||
|
@ -610,11 +609,6 @@ class TestBaseSubClass(TestBase):
|
||||||
self.assertRaisesRegexp(AnsibleParserError, 'cannot have empty values',
|
self.assertRaisesRegexp(AnsibleParserError, 'cannot have empty values',
|
||||||
bsc.post_validate, templar)
|
bsc.post_validate, templar)
|
||||||
|
|
||||||
def test_attr_barelist(self):
|
|
||||||
ds = {'test_attr_barelist': 'comma,separated,values'}
|
|
||||||
bsc = self._base_validate(ds)
|
|
||||||
self.assertEquals(['comma', 'separated', 'values'], bsc._attributes['test_attr_barelist'])
|
|
||||||
|
|
||||||
def test_attr_unknown(self):
|
def test_attr_unknown(self):
|
||||||
a_list = ['some string']
|
a_list = ['some string']
|
||||||
ds = {'test_attr_unknown_isa': a_list}
|
ds = {'test_attr_unknown_isa': a_list}
|
||||||
|
|
Loading…
Reference in a new issue