Add symlinks sanity test. (#46467)
* Add symlinks sanity test. * Replace legacy test symlinks with actual content. * Remove dir symlink from template_jinja2_latest. * Update import test to use generated library dir. * Fix copy test symlink setup.
This commit is contained in:
parent
a4961ff32a
commit
e2b6047514
21 changed files with 259 additions and 16 deletions
6
docs/docsite/rst/dev_guide/testing/sanity/symlinks.rst
Normal file
6
docs/docsite/rst/dev_guide/testing/sanity/symlinks.rst
Normal file
|
@ -0,0 +1,6 @@
|
|||
Sanity Tests » symlinks
|
||||
=======================
|
||||
|
||||
Symbolic links are only permitted for files that exist to ensure proper tarball generation during a release.
|
||||
|
||||
If other types of symlinks are needed for tests they must be created as part of the test.
|
|
@ -1 +0,0 @@
|
|||
/tmp/ansible-test-abs-link
|
|
@ -1 +0,0 @@
|
|||
/tmp/ansible-test-abs-link-dir
|
|
@ -1 +0,0 @@
|
|||
invalid
|
|
@ -1 +0,0 @@
|
|||
../invalid
|
|
@ -1 +0,0 @@
|
|||
/tmp/ansible-test-link-dir/out_of_tree_circle
|
|
@ -1 +0,0 @@
|
|||
../subdir2/subdir3
|
|
@ -9,15 +9,25 @@
|
|||
local_temp_dir: '{{ tempfile_result.stdout }}'
|
||||
# output_dir is hardcoded in test/runner/lib/executor.py and created there
|
||||
remote_dir: '{{ output_dir }}'
|
||||
symlinks:
|
||||
ansible-test-abs-link: /tmp/ansible-test-abs-link
|
||||
ansible-test-abs-link-dir: /tmp/ansible-test-abs-link-dir
|
||||
circles: ../
|
||||
invalid: invalid
|
||||
invalid2: ../invalid
|
||||
out_of_tree_circle: /tmp/ansible-test-link-dir/out_of_tree_circle
|
||||
subdir3: ../subdir2/subdir3
|
||||
|
||||
- file: path={{local_temp_dir}} state=directory
|
||||
name: ensure temp dir exists
|
||||
|
||||
# file cannot do this properly, use command instead
|
||||
- name: Create circular symbolic link
|
||||
command: ln -s ../ circles
|
||||
- name: Create symbolic link
|
||||
command: "ln -s '{{ item.value }}' '{{ item.key }}'"
|
||||
args:
|
||||
chdir: '{{role_path}}/files/subdir/subdir1'
|
||||
warn: no
|
||||
with_dict: "{{ symlinks }}"
|
||||
|
||||
- name: Create remote unprivileged remote user
|
||||
user:
|
||||
|
@ -55,11 +65,12 @@
|
|||
state: absent
|
||||
connection: local
|
||||
|
||||
- name: Remove circular symbolic link
|
||||
- name: Remove symbolic link
|
||||
file:
|
||||
path: '{{ role_path }}/files/subdir/subdir1/circles'
|
||||
path: '{{ role_path }}/files/subdir/subdir1/{{ item.key }}'
|
||||
state: absent
|
||||
connection: local
|
||||
with_dict: "{{ symlinks }}"
|
||||
|
||||
- name: Remote unprivileged remote user
|
||||
user:
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
../../template
|
|
@ -18,4 +18,7 @@ source "${MYTMPDIR}/jinja2/bin/activate"
|
|||
|
||||
pip install -U jinja2
|
||||
|
||||
ANSIBLE_ROLES_PATH="$(dirname "$(pwd)")"
|
||||
export ANSIBLE_ROLES_PATH
|
||||
|
||||
ansible-playbook -i ../../inventory main.yml -e @../../integration_config.yml -v "$@"
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
../../integration/targets/setup_ec2
|
2
test/legacy/roles/setup_ec2/defaults/main.yml
Normal file
2
test/legacy/roles/setup_ec2/defaults/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
resource_prefix: 'ansible-testing-'
|
119
test/legacy/roles/setup_ec2/tasks/common.yml
Normal file
119
test/legacy/roles/setup_ec2/tasks/common.yml
Normal file
|
@ -0,0 +1,119 @@
|
|||
---
|
||||
|
||||
# ============================================================
|
||||
- name: test with no parameters
|
||||
action: "{{module_name}}"
|
||||
register: result
|
||||
ignore_errors: true
|
||||
|
||||
- name: assert failure when called with no parameters
|
||||
assert:
|
||||
that:
|
||||
- 'result.failed'
|
||||
- 'result.msg == "missing required arguments: name"'
|
||||
|
||||
# ============================================================
|
||||
- name: test with only name
|
||||
action: "{{module_name}} name={{ec2_key_name}}"
|
||||
register: result
|
||||
ignore_errors: true
|
||||
|
||||
- name: assert failure when called with only 'name'
|
||||
assert:
|
||||
that:
|
||||
- 'result.failed'
|
||||
- 'result.msg == "Either region or ec2_url must be specified"'
|
||||
|
||||
# ============================================================
|
||||
- name: test invalid region parameter
|
||||
action: "{{module_name}} name='{{ec2_key_name}}' region='asdf querty 1234'"
|
||||
register: result
|
||||
ignore_errors: true
|
||||
|
||||
- name: assert invalid region parameter
|
||||
assert:
|
||||
that:
|
||||
- 'result.failed'
|
||||
- 'result.msg.startswith("value of region must be one of:")'
|
||||
|
||||
# ============================================================
|
||||
- name: test valid region parameter
|
||||
action: "{{module_name}} name='{{ec2_key_name}}' region='{{ec2_region}}'"
|
||||
register: result
|
||||
ignore_errors: true
|
||||
|
||||
- name: assert valid region parameter
|
||||
assert:
|
||||
that:
|
||||
- 'result.failed'
|
||||
- 'result.msg.startswith("No handler was ready to authenticate.")'
|
||||
|
||||
# ============================================================
|
||||
- name: test environment variable EC2_REGION
|
||||
action: "{{module_name}} name='{{ec2_key_name}}'"
|
||||
environment:
|
||||
EC2_REGION: '{{ec2_region}}'
|
||||
register: result
|
||||
ignore_errors: true
|
||||
|
||||
- name: assert environment variable EC2_REGION
|
||||
assert:
|
||||
that:
|
||||
- 'result.failed'
|
||||
- 'result.msg.startswith("No handler was ready to authenticate.")'
|
||||
|
||||
# ============================================================
|
||||
- name: test invalid ec2_url parameter
|
||||
action: "{{module_name}} name='{{ec2_key_name}}'"
|
||||
environment:
|
||||
EC2_URL: bogus.example.com
|
||||
register: result
|
||||
ignore_errors: true
|
||||
|
||||
- name: assert invalid ec2_url parameter
|
||||
assert:
|
||||
that:
|
||||
- 'result.failed'
|
||||
- 'result.msg.startswith("No handler was ready to authenticate.")'
|
||||
|
||||
# ============================================================
|
||||
- name: test valid ec2_url parameter
|
||||
action: "{{module_name}} name='{{ec2_key_name}}'"
|
||||
environment:
|
||||
EC2_URL: '{{ec2_url}}'
|
||||
register: result
|
||||
ignore_errors: true
|
||||
|
||||
- name: assert valid ec2_url parameter
|
||||
assert:
|
||||
that:
|
||||
- 'result.failed'
|
||||
- 'result.msg.startswith("No handler was ready to authenticate.")'
|
||||
|
||||
# ============================================================
|
||||
- name: test credentials from environment
|
||||
action: "{{module_name}} name='{{ec2_key_name}}'"
|
||||
environment:
|
||||
EC2_REGION: '{{ec2_region}}'
|
||||
EC2_ACCESS_KEY: bogus_access_key
|
||||
EC2_SECRET_KEY: bogus_secret_key
|
||||
register: result
|
||||
ignore_errors: true
|
||||
|
||||
- name: assert ec2_key with valid ec2_url
|
||||
assert:
|
||||
that:
|
||||
- 'result.failed'
|
||||
- '"EC2ResponseError: 401 Unauthorized" in result.msg'
|
||||
|
||||
# ============================================================
|
||||
- name: test credential parameters
|
||||
action: "{{module_name}} name='{{ec2_key_name}}' ec2_region='{{ec2_region}}' ec2_access_key=bogus_access_key ec2_secret_key=bogus_secret_key"
|
||||
register: result
|
||||
ignore_errors: true
|
||||
|
||||
- name: assert credential parameters
|
||||
assert:
|
||||
that:
|
||||
- 'result.failed'
|
||||
- '"EC2ResponseError: 401 Unauthorized" in result.msg'
|
3
test/legacy/roles/setup_ec2/vars/main.yml
Normal file
3
test/legacy/roles/setup_ec2/vars/main.yml
Normal file
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
ec2_url: ec2.amazonaws.com
|
||||
ec2_region: us-east-1
|
|
@ -1 +0,0 @@
|
|||
../../integration/targets/setup_sshkey
|
55
test/legacy/roles/setup_sshkey/tasks/main.yml
Normal file
55
test/legacy/roles/setup_sshkey/tasks/main.yml
Normal file
|
@ -0,0 +1,55 @@
|
|||
# (c) 2014, James Laska <jlaska@ansible.com>
|
||||
|
||||
# This file is part of Ansible
|
||||
#
|
||||
# Ansible is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Ansible is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
- name: create a temp file
|
||||
tempfile:
|
||||
state: file
|
||||
register: sshkey_file
|
||||
tags:
|
||||
- prepare
|
||||
|
||||
- name: generate sshkey
|
||||
shell: echo 'y' | ssh-keygen -P '' -f {{ sshkey_file.path }}
|
||||
tags:
|
||||
- prepare
|
||||
|
||||
- name: create another temp file
|
||||
tempfile:
|
||||
state: file
|
||||
register: another_sshkey_file
|
||||
tags:
|
||||
- prepare
|
||||
|
||||
- name: generate another_sshkey
|
||||
shell: echo 'y' | ssh-keygen -P '' -f {{ another_sshkey_file.path }}
|
||||
tags:
|
||||
- prepare
|
||||
|
||||
- name: record fingerprint
|
||||
shell: openssl rsa -in {{ sshkey_file.path }} -pubout -outform DER 2>/dev/null | openssl md5 -c
|
||||
register: fingerprint
|
||||
tags:
|
||||
- prepare
|
||||
|
||||
- name: set facts for future roles
|
||||
set_fact:
|
||||
sshkey: '{{ sshkey_file.path }}'
|
||||
key_material: "{{ lookup('file', sshkey_file.path ~ '.pub') }}"
|
||||
another_key_material: "{{ lookup('file', another_sshkey_file.path ~ '.pub') }}"
|
||||
fingerprint: '{{ fingerprint.stdout.split()[1] }}'
|
||||
tags:
|
||||
- prepare
|
|
@ -20,6 +20,7 @@ from lib.util import (
|
|||
find_python,
|
||||
read_lines_without_comments,
|
||||
parse_to_list_of_dict,
|
||||
make_dirs,
|
||||
)
|
||||
|
||||
from lib.ansible_util import (
|
||||
|
@ -81,9 +82,24 @@ class ImportTest(SanityMultipleVersion):
|
|||
if not args.explain:
|
||||
os.symlink(os.path.abspath('test/sanity/import/importer.py'), importer_path)
|
||||
|
||||
# create a minimal python library
|
||||
python_path = os.path.abspath('test/runner/.tox/import/lib')
|
||||
ansible_path = os.path.join(python_path, 'ansible')
|
||||
ansible_init = os.path.join(ansible_path, '__init__.py')
|
||||
ansible_link = os.path.join(ansible_path, 'module_utils')
|
||||
|
||||
if not args.explain:
|
||||
make_dirs(ansible_path)
|
||||
|
||||
with open(ansible_init, 'w'):
|
||||
pass
|
||||
|
||||
if not os.path.exists(ansible_link):
|
||||
os.symlink('../../../../../../lib/ansible/module_utils', ansible_link)
|
||||
|
||||
# activate the virtual environment
|
||||
env['PATH'] = '%s:%s' % (virtual_environment_bin, env['PATH'])
|
||||
env['PYTHONPATH'] = os.path.abspath('test/sanity/import/lib')
|
||||
env['PYTHONPATH'] = python_path
|
||||
|
||||
# make sure coverage is available in the virtual environment if needed
|
||||
if args.coverage:
|
||||
|
|
4
test/sanity/code-smell/symlinks.json
Normal file
4
test/sanity/code-smell/symlinks.json
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"always": true,
|
||||
"output": "path-message"
|
||||
}
|
35
test/sanity/code-smell/symlinks.py
Executable file
35
test/sanity/code-smell/symlinks.py
Executable file
|
@ -0,0 +1,35 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
|
||||
|
||||
def main():
|
||||
skip_dirs = set([
|
||||
'.tox',
|
||||
])
|
||||
|
||||
for root, dirs, files in os.walk('.'):
|
||||
for skip_dir in skip_dirs:
|
||||
if skip_dir in dirs:
|
||||
dirs.remove(skip_dir)
|
||||
|
||||
if root == '.':
|
||||
root = ''
|
||||
elif root.startswith('./'):
|
||||
root = root[2:]
|
||||
|
||||
for file in files:
|
||||
path = os.path.join(root, file)
|
||||
|
||||
if not os.path.exists(path):
|
||||
print('%s: broken symlinks are not allowed' % path)
|
||||
|
||||
for directory in dirs:
|
||||
path = os.path.join(root, directory)
|
||||
|
||||
if os.path.islink(path):
|
||||
print('%s: symlinks to directories are not allowed' % path)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1 +0,0 @@
|
|||
"""Empty placeholder for import sanity test."""
|
|
@ -1 +0,0 @@
|
|||
../../../../../lib/ansible/module_utils
|
Loading…
Reference in a new issue