Fix ansible-test default image. (#31966)
* Add openssh-client to default docker container. * Include Azure requirements in default container. To do so, handling of pip requirements was updated to install each set of requirements separately and then run a verification pass to make sure there are no conflicts between requirements. * Add missing --docker-no-pull option. * Add documentation for the azure-requirements test.
This commit is contained in:
parent
93288ba9b6
commit
36b13e3e3d
10 changed files with 159 additions and 21 deletions
|
@ -0,0 +1,10 @@
|
||||||
|
Sanity Tests » azure-requirements
|
||||||
|
=================================
|
||||||
|
|
||||||
|
Update the Azure integration test requirements file when changes are made to the Azure packaging requirements file:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
cp packaging/requirements/requirements-azure.txt test/runner/requirements/integration.cloud.azure.txt
|
||||||
|
|
||||||
|
This copy of the requirements file is used when building the ``ansible/ansible:default`` Docker container from ``test/runner/Dockerfile``.
|
0
test/integration/targets/setup_azure/aliases
Normal file
0
test/integration/targets/setup_azure/aliases
Normal file
|
@ -1,2 +0,0 @@
|
||||||
- pip:
|
|
||||||
requirements: '{{ role_path }}/../../../../packaging/requirements/requirements-azure.txt'
|
|
|
@ -13,6 +13,7 @@ RUN apt-get update -y && \
|
||||||
libxslt1-dev \
|
libxslt1-dev \
|
||||||
locales \
|
locales \
|
||||||
make \
|
make \
|
||||||
|
openssh-client \
|
||||||
python2.6-dev \
|
python2.6-dev \
|
||||||
python2.7-dev \
|
python2.7-dev \
|
||||||
python3.5-dev \
|
python3.5-dev \
|
||||||
|
|
|
@ -11,13 +11,60 @@ requirements=()
|
||||||
|
|
||||||
for requirement in *.txt; do
|
for requirement in *.txt; do
|
||||||
if [ "${requirement}" != "constraints.txt" ]; then
|
if [ "${requirement}" != "constraints.txt" ]; then
|
||||||
requirements+=("-r" "${requirement}")
|
requirements+=("${requirement}")
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
for python_version in "${python_versions[@]}"; do
|
for python_version in "${python_versions[@]}"; do
|
||||||
|
version_requirements=()
|
||||||
|
|
||||||
|
for requirement in "${requirements[@]}"; do
|
||||||
|
case "${python_version}" in
|
||||||
|
"2.6")
|
||||||
|
case "${requirement}" in
|
||||||
|
"integration.cloud.azure.txt") continue ;;
|
||||||
|
esac
|
||||||
|
esac
|
||||||
|
|
||||||
|
version_requirements+=("${requirement}")
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "==> Installing pip for python ${python_version} ..."
|
||||||
|
|
||||||
set -x
|
set -x
|
||||||
"python${python_version}" /tmp/get-pip.py -c constraints.txt
|
"python${python_version}" /tmp/get-pip.py -c constraints.txt
|
||||||
"pip${python_version}" install --disable-pip-version-check -c constraints.txt "${requirements[@]}"
|
|
||||||
set +x
|
set +x
|
||||||
|
|
||||||
|
echo "==> Installing requirements for python ${python_version} ..."
|
||||||
|
|
||||||
|
for requirement in "${version_requirements[@]}"; do
|
||||||
|
set -x
|
||||||
|
"pip${python_version}" install --disable-pip-version-check -c constraints.txt -r "${requirement}"
|
||||||
|
set +x
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "==> Checking for requirements conflicts for ${python_version} ..."
|
||||||
|
|
||||||
|
after=$("pip${python_version}" list)
|
||||||
|
|
||||||
|
for requirement in "${version_requirements[@]}"; do
|
||||||
|
before="${after}"
|
||||||
|
|
||||||
|
set -x
|
||||||
|
"pip${python_version}" install --disable-pip-version-check -c constraints.txt -r "${requirement}"
|
||||||
|
set +x
|
||||||
|
|
||||||
|
after=$("pip${python_version}" list)
|
||||||
|
|
||||||
|
if [ "${before}" != "${after}" ]; then
|
||||||
|
echo "==> Conflicts detected in requirements for python ${python_version}: ${requirement}"
|
||||||
|
echo ">>> Before"
|
||||||
|
echo "${before}"
|
||||||
|
echo ">>> After"
|
||||||
|
echo "${after}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "==> Finished with requirements for python ${python_version}."
|
||||||
done
|
done
|
||||||
|
|
|
@ -13,6 +13,7 @@ import textwrap
|
||||||
import functools
|
import functools
|
||||||
import shutil
|
import shutil
|
||||||
import stat
|
import stat
|
||||||
|
import pipes
|
||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
import atexit
|
import atexit
|
||||||
|
@ -162,30 +163,78 @@ def install_command_requirements(args):
|
||||||
if args.junit:
|
if args.junit:
|
||||||
packages.append('junit-xml')
|
packages.append('junit-xml')
|
||||||
|
|
||||||
extras = []
|
commands = [generate_pip_install(args.command, packages=packages)]
|
||||||
|
|
||||||
if isinstance(args, IntegrationConfig):
|
if isinstance(args, IntegrationConfig):
|
||||||
extras += ['cloud.%s' % cp for cp in get_cloud_platforms(args)]
|
for cloud_platform in get_cloud_platforms(args):
|
||||||
|
commands.append(generate_pip_install('%s.cloud.%s' % (args.command, cloud_platform)))
|
||||||
|
|
||||||
cmd = generate_pip_install(args.command, packages, extras)
|
# only look for changes when more than one requirements file is needed
|
||||||
|
detect_pip_changes = len(commands) > 1
|
||||||
|
|
||||||
if not cmd:
|
# first pass to install requirements, changes expected unless environment is already set up
|
||||||
return
|
changes = run_pip_commands(args, commands, detect_pip_changes)
|
||||||
|
|
||||||
try:
|
if not changes:
|
||||||
run_command(args, cmd)
|
return # no changes means we can stop early
|
||||||
except SubprocessError as ex:
|
|
||||||
if ex.status != 2:
|
|
||||||
raise
|
|
||||||
|
|
||||||
# If pip is too old it won't understand the arguments we passed in, so we'll need to upgrade it.
|
# second pass to check for conflicts in requirements, changes are not expected here
|
||||||
|
changes = run_pip_commands(args, commands, detect_pip_changes)
|
||||||
|
|
||||||
# Installing "coverage" on ubuntu 16.04 fails with the error:
|
if not changes:
|
||||||
# AttributeError: 'Requirement' object has no attribute 'project_name'
|
return # no changes means no conflicts
|
||||||
# See: https://bugs.launchpad.net/ubuntu/xenial/+source/python-pip/+bug/1626258
|
|
||||||
# Upgrading pip works around the issue.
|
raise ApplicationError('Conflicts detected in requirements. The following commands reported changes during verification:\n%s' %
|
||||||
run_command(args, ['pip', 'install', '--upgrade', 'pip'])
|
'\n'.join((' '.join(pipes.quote(c) for c in cmd) for cmd in changes)))
|
||||||
run_command(args, cmd)
|
|
||||||
|
|
||||||
|
def run_pip_commands(args, commands, detect_pip_changes=False):
|
||||||
|
"""
|
||||||
|
:type args: EnvironmentConfig
|
||||||
|
:type commands: list[list[str]]
|
||||||
|
:type detect_pip_changes: bool
|
||||||
|
:rtype: list[list[str]]
|
||||||
|
"""
|
||||||
|
changes = []
|
||||||
|
|
||||||
|
after_list = pip_list(args) if detect_pip_changes else None
|
||||||
|
|
||||||
|
for cmd in commands:
|
||||||
|
if not cmd:
|
||||||
|
continue
|
||||||
|
|
||||||
|
before_list = after_list
|
||||||
|
|
||||||
|
try:
|
||||||
|
run_command(args, cmd)
|
||||||
|
except SubprocessError as ex:
|
||||||
|
if ex.status != 2:
|
||||||
|
raise
|
||||||
|
|
||||||
|
# If pip is too old it won't understand the arguments we passed in, so we'll need to upgrade it.
|
||||||
|
|
||||||
|
# Installing "coverage" on ubuntu 16.04 fails with the error:
|
||||||
|
# AttributeError: 'Requirement' object has no attribute 'project_name'
|
||||||
|
# See: https://bugs.launchpad.net/ubuntu/xenial/+source/python-pip/+bug/1626258
|
||||||
|
# Upgrading pip works around the issue.
|
||||||
|
run_command(args, ['pip', 'install', '--upgrade', 'pip'])
|
||||||
|
run_command(args, cmd)
|
||||||
|
|
||||||
|
after_list = pip_list(args) if detect_pip_changes else None
|
||||||
|
|
||||||
|
if before_list != after_list:
|
||||||
|
changes.append(cmd)
|
||||||
|
|
||||||
|
return changes
|
||||||
|
|
||||||
|
|
||||||
|
def pip_list(args):
|
||||||
|
"""
|
||||||
|
:type args: EnvironmentConfig
|
||||||
|
:rtype: str
|
||||||
|
"""
|
||||||
|
stdout, _ = run_command(args, ['pip', 'list'], capture=True, always=True)
|
||||||
|
return stdout
|
||||||
|
|
||||||
|
|
||||||
def generate_egg_info(args):
|
def generate_egg_info(args):
|
||||||
|
|
16
test/runner/requirements/integration.cloud.azure.txt
Normal file
16
test/runner/requirements/integration.cloud.azure.txt
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
packaging
|
||||||
|
requests[security]
|
||||||
|
azure-mgmt-compute>=2.0.0,<3
|
||||||
|
azure-mgmt-network>=1.3.0,<2
|
||||||
|
azure-mgmt-storage>=1.2.0,<2
|
||||||
|
azure-mgmt-resource>=1.1.0,<2
|
||||||
|
azure-storage>=0.35.1,<0.36
|
||||||
|
azure-cli-core>=2.0.12,<3
|
||||||
|
msrest!=0.4.15
|
||||||
|
msrestazure>=0.4.11,<0.5
|
||||||
|
azure-mgmt-dns>=1.0.1,<2
|
||||||
|
azure-mgmt-keyvault>=0.40.0,<0.41
|
||||||
|
azure-mgmt-batch>=4.1.0,<5
|
||||||
|
azure-mgmt-sql>=0.7.1,<0.8
|
||||||
|
azure-mgmt-web>=0.32.0,<0.33
|
||||||
|
azure-mgmt-containerservice>=1.0.0
|
|
@ -255,6 +255,8 @@ def parse_args():
|
||||||
targets=walk_network_integration_targets,
|
targets=walk_network_integration_targets,
|
||||||
config=NetworkIntegrationConfig)
|
config=NetworkIntegrationConfig)
|
||||||
|
|
||||||
|
add_extra_docker_options(network_integration, integration=False)
|
||||||
|
|
||||||
network_integration.add_argument('--platform',
|
network_integration.add_argument('--platform',
|
||||||
metavar='PLATFORM',
|
metavar='PLATFORM',
|
||||||
action='append',
|
action='append',
|
||||||
|
@ -272,6 +274,8 @@ def parse_args():
|
||||||
targets=walk_windows_integration_targets,
|
targets=walk_windows_integration_targets,
|
||||||
config=WindowsIntegrationConfig)
|
config=WindowsIntegrationConfig)
|
||||||
|
|
||||||
|
add_extra_docker_options(windows_integration, integration=False)
|
||||||
|
|
||||||
windows_integration.add_argument('--windows',
|
windows_integration.add_argument('--windows',
|
||||||
metavar='VERSION',
|
metavar='VERSION',
|
||||||
action='append',
|
action='append',
|
||||||
|
|
12
test/sanity/code-smell/azure-requirements.py
Executable file
12
test/sanity/code-smell/azure-requirements.py
Executable file
|
@ -0,0 +1,12 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
"""Make sure the Azure requirements files match."""
|
||||||
|
|
||||||
|
import filecmp
|
||||||
|
|
||||||
|
src = 'packaging/requirements/requirements-azure.txt'
|
||||||
|
dst = 'test/runner/requirements/integration.cloud.azure.txt'
|
||||||
|
|
||||||
|
if not filecmp.cmp(src, dst):
|
||||||
|
print('Update the Azure integration test requirements with the packaging test requirements:')
|
||||||
|
print('cp %s %s' % (src, dst))
|
||||||
|
exit(1)
|
|
@ -5,6 +5,7 @@ constraints=$(
|
||||||
| grep -v '(sanity_ok)$' \
|
| grep -v '(sanity_ok)$' \
|
||||||
| sed 's/ *;.*$//; s/ #.*$//' \
|
| sed 's/ *;.*$//; s/ #.*$//' \
|
||||||
| grep -v '/constraints.txt:' \
|
| grep -v '/constraints.txt:' \
|
||||||
|
| grep -v '/integration.cloud.azure.txt:' \
|
||||||
| grep '[<>=]'
|
| grep '[<>=]'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue