Update Ansible GitHub workflows

The workflows committed in the first commit were missing the
installation of required dependencies and other fixes.

Signed-off-by: Felix Matouschek <fmatouschek@redhat.com>
This commit is contained in:
Felix Matouschek
2023-07-17 14:20:39 +02:00
parent e1499d4aae
commit 68f5cc8e33
16 changed files with 505 additions and 40 deletions

View File

@@ -7,6 +7,18 @@ on:
schedule:
- cron: '0 6 * * *'
jobs:
prereq:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2
with:
path: ansible_collections/kubernetes/kubevirt
fetch-depth: 0
- run: |
mkdir -p /home/runner/.kube/
cp -rp ${GITHUB_WORKSPACE}/ansible_collections/kubernetes/kubevirt/tests/.kubeconfig /home/runner/.kube/config
cat /home/runner/.kube/config
sanity:
uses: ansible-network/github_actions/.github/workflows/sanity.yml@main
with:
@@ -71,50 +83,232 @@ jobs:
{
"ansible-version": "devel",
"python-version": "3.8"
},
{
"ansible-version": "devel",
"python-version": "3.9"
}
]
integration:
unit-source:
uses: ansible-network/github_actions/.github/workflows/unit_source.yml@main
needs:
- prereq
with:
matrix_exclude: >-
[
{
"python-version": "3.11"
},
{
"ansible-version": "stable-2.12",
"python-version": "3.7"
},
{
"ansible-version": "stable-2.13",
"python-version": "3.7"
},
{
"ansible-version": "stable-2.12",
"python-version": "3.8"
},
{
"ansible-version": "stable-2.13",
"python-version": "3.8"
},
{
"ansible-version": "stable-2.14",
"python-version": "3.7"
},
{
"ansible-version": "stable-2.14",
"python-version": "3.8"
},
{
"ansible-version": "stable-2.15",
"python-version": "3.7"
},
{
"ansible-version": "stable-2.15",
"python-version": "3.8"
},
{
"ansible-version": "milestone",
"python-version": "3.7"
},
{
"ansible-version": "milestone",
"python-version": "3.8"
},
{
"ansible-version": "devel",
"python-version": "3.7"
},
{
"ansible-version": "devel",
"python-version": "3.8"
},
{
"ansible-version": "devel",
"python-version": "3.9"
}
]
collection_pre_install: ''
splitter:
env:
source_dir: "./source"
runs-on: ubuntu-latest
name: I (${{ matrix.ansible }}+py${{ matrix.python }})
outputs:
test_targets: ${{ steps.display.outputs.test_targets }}
steps:
- name: Checkout the collection repository
uses: actions/checkout@v3
with:
path: ${{ env.source_dir }}
fetch-depth: "0"
- name: list changes for pull request
id: splitter
uses: ansible-network/github_actions/.github/actions/ansible_test_splitter@main
with:
collections_to_test: ${{ env.source_dir }}
total_jobs: 8
- name: display targets
id: display
run: echo "test_targets=${{ steps.splitter.outputs.test_targets }}" >> $GITHUB_OUTPUT
shell: bash
integration:
needs:
- splitter
env:
source: "./source"
cloud_common: "./cloudcommon"
ansible_posix: "./ansible_posix"
test_targets: ${{ needs.splitter.outputs.test_targets }}
runs-on: ubuntu-latest
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
ansible:
- stable-2.9
- stable-2.11
ansible-version:
- stable-2.12
- stable-2.13
- milestone
- devel
python:
- '3.8'
- '3.9'
- '3.10'
python-version:
- "3.8"
- "3.9"
exclude:
# Because ansible-test doesn't support Python 3.9 for Ansible 2.9
# and Python 3.10 is supported in 2.12 or later.
- ansible: stable-2.9
python: '3.9'
- ansible: stable-2.9
python: '3.10'
- ansible: stable-2.10
python: '3.10'
- ansible: stable-2.11
python: '3.10'
- ansible-version: stable-2.9
python-version: 3.9
- ansible-version: stable-2.9
python-version: 3.10
- ansible-version: stable-2.9
python-version: 3.11
- ansible-version: stable-2.12
python-version: 3.11
- ansible-version: stable-2.13
python-version: 3.11
- ansible-version: stable-2.14
python-version: 3.8
- ansible-version: stable-2.15
python-version: 3.8
- ansible-version: milestone
python-version: 3.8
- ansible-version: devel
python-version: 3.8
enable-turbo-mode:
- true
- false
job-index: [1, 2, 3, 4, 5, 6, 7, 8]
name: "integration-py${{ matrix.python-version }}-${{ matrix.ansible-version }}-turbo-mode=${{ matrix.enable-turbo-mode }}-${{ matrix.job-index }}"
steps:
- name: >-
Perform integration testing against
Ansible version ${{ matrix.ansible }}
under Python ${{ matrix.python }}
uses: ansible-community/ansible-test-gh-action@release/v1
- name: Read ansible-test targets
id: read-targets
run: >-
echo "ansible_test_targets=$(echo "${{ env.test_targets }}" | sed s/';'/'\n'/g |
grep "kubernetes.core-${{ matrix.job-index }}" | cut -d ':' -f2 | sed s/','/' '/g)" >> $GITHUB_OUTPUT
shell: bash
- name: Display targets
run: >-
echo "targets to test: $ANSIBLE_TARGETS"
shell: bash
env:
ANSIBLE_TARGETS: ${{ steps.read-targets.outputs.ansible_test_targets }}
- name: Checkout kubernetes.core repository
uses: actions/checkout@v3
with:
ansible-core-version: ${{ matrix.ansible }}
# OPTIONAL command to run before invoking `ansible-test integration`
# pre-test-cmd:
target-python-version: ${{ matrix.python }}
testing-type: integration
# OPTIONAL If your integration tests require code
# from other collections, install them like this
test-deps: >-
ansible.netcommon
kubernetes.core
path: ${{ env.source }}
fetch-depth: "0"
if: steps.read-targets.outputs.ansible_test_targets != ''
- name: checkout ansible-collections/cloud.common
uses: ansible-network/github_actions/.github/actions/checkout_dependency@main
with:
repository: ansible-collections/cloud.common
path: ${{ env.cloud_common }}
ref: main
if: steps.read-targets.outputs.ansible_test_targets != ''
- name: checkout ansible-collections/ansible.posix
uses: ansible-network/github_actions/.github/actions/checkout_dependency@main
with:
repository: ansible-collections/ansible.posix
path: ${{ env.ansible_posix }}
ref: main
if: steps.read-targets.outputs.ansible_test_targets != ''
- name: install kubernetes.core collection
id: install-collection
uses: ansible-network/github_actions/.github/actions/build_install_collection@main
with:
install_python_dependencies: true
source_path: ${{ env.source }}
if: steps.read-targets.outputs.ansible_test_targets != ''
- name: install cloud.common collection
uses: ansible-network/github_actions/.github/actions/build_install_collection@main
with:
install_python_dependencies: true
source_path: ${{ env.cloud_common }}
if: steps.read-targets.outputs.ansible_test_targets != ''
- name: install ansible.posix collection
uses: ansible-network/github_actions/.github/actions/build_install_collection@main
with:
install_python_dependencies: true
source_path: ${{ env.ansible_posix }}
if: steps.read-targets.outputs.ansible_test_targets != ''
- name: create kubernetes cluster
uses: helm/kind-action@v1.4.0
if: steps.read-targets.outputs.ansible_test_targets != ''
- name: Run integration tests
uses: ansible-network/github_actions/.github/actions/ansible_test_integration@main
with:
collection_path: ${{ steps.install-collection.outputs.collection_path }}
python_version: ${{ matrix.python-version }}
ansible_version: ${{ matrix.ansible-version }}
ansible_test_targets: ${{ steps.read-targets.outputs.ansible_test_targets }}
ansible_test_environment: |
ENABLE_TURBO_MODE=${{ matrix.enable-turbo-mode }}
if: steps.read-targets.outputs.ansible_test_targets != ''
all_green:
if: ${{ always() }}
needs:
- sanity
- unit-source
- integration
runs-on: ubuntu-latest
steps:
- run: >-
python -c "assert set([
'${{ needs.unit-source.result }}',
'${{ needs.integration.result }}'
]) == {'success'}"
- run: >-
python -c "assert '${{ needs.sanity.result }}'
in ['success', 'failure']"

View File

@@ -48,10 +48,7 @@ jobs:
- name: Create default collection path
run: |
mkdir -p /home/runner/.ansible/
cp -rp /home/runner/work/kubevirt/kubevirt/ansible_collections /home/runner/.ansible/collections/
ls -l /home/runner/.ansible/collections/ansible_collections/
ls -l /home/runner/.ansible/collections/ansible_collections/kubernetes/
ls -l /home/runner/.ansible/collections/ansible_collections/kubernetes/kubevirt/
cp -rp ${GITHUB_WORKSPACE}/ansible_collections /home/runner/.ansible/collections/
- name: Create changelog and documentation
uses: ansible-middleware/collection-docs-action@main

9
test-requirements.txt Normal file
View File

@@ -0,0 +1,9 @@
kubernetes-validate
coverage==4.5.4
mock
pytest
pytest-xdist
pytest-mock
pytest-forked
virtualenv
pytest-ansible

18
tests/.kubeconfig Normal file
View File

@@ -0,0 +1,18 @@
apiVersion: v1
clusters:
- cluster:
insecure-skip-tls-verify: true
server: http://localhost:12345
name: development
contexts:
- context:
cluster: development
user: developer
name: dev-frontend
current-context: dev-frontend
kind: Config
preferences: {}
users:
- name: developer
user:
token: ZDNffLzSlp8aSS0fht_tRnPMTOjxqgJGCyi_iy0ecUw

View File

@@ -0,0 +1,2 @@
[testgroup]
testhost ansible_connection="local" ansible_pipelining="yes" ansible_python_interpreter="/home/guido/Development/virtualenv/2.15/bin/python"

View File

View File

View File

View File

View File

View File

View File

44
tests/unit/conftest.py Normal file
View File

@@ -0,0 +1,44 @@
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import json
import sys
from io import BytesIO
import pytest
import ansible.module_utils.basic
from ansible.module_utils.six import string_types
from ansible.module_utils._text import to_bytes
from ansible.module_utils.common._collections_compat import MutableMapping
@pytest.fixture
def stdin(mocker, request):
old_args = ansible.module_utils.basic._ANSIBLE_ARGS
ansible.module_utils.basic._ANSIBLE_ARGS = None
old_argv = sys.argv
sys.argv = ["ansible_unittest"]
if isinstance(request.param, string_types):
args = request.param
elif isinstance(request.param, MutableMapping):
if "ANSIBLE_MODULE_ARGS" not in request.param:
request.param = {"ANSIBLE_MODULE_ARGS": request.param}
if "_ansible_remote_tmp" not in request.param["ANSIBLE_MODULE_ARGS"]:
request.param["ANSIBLE_MODULE_ARGS"]["_ansible_remote_tmp"] = "/tmp"
if "_ansible_keep_remote_files" not in request.param["ANSIBLE_MODULE_ARGS"]:
request.param["ANSIBLE_MODULE_ARGS"]["_ansible_keep_remote_files"] = False
args = json.dumps(request.param)
else:
raise Exception("Malformed data to the stdin pytest fixture")
fake_stdin = BytesIO(to_bytes(args, errors="surrogate_or_strict"))
mocker.patch("ansible.module_utils.basic.sys.stdin", mocker.MagicMock())
mocker.patch("ansible.module_utils.basic.sys.stdin.buffer", fake_stdin)
yield fake_stdin
ansible.module_utils.basic._ANSIBLE_ARGS = old_args
sys.argv = old_argv

View File

@@ -0,0 +1,147 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2021, Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import unittest
from unittest.mock import patch, ANY
from ansible.module_utils import basic
from ansible_collections.kubernetes.core.plugins.module_utils.k8s import runner
from ansible_collections.kubernetes.kubevirt.plugins.modules import kubevirt_vm
from ansible_collections.kubernetes.kubevirt.tests.unit.utils.ansible_module_mock import (
AnsibleFailJson,
AnsibleExitJson,
exit_json,
fail_json,
set_module_args,
get_api_client
)
FIXTURE1 = {
"apiVersion": "kubevirt.io/v1",
"kind": "VirtualMachine",
"metadata": {
"name": "testvm",
"namespace": "default",
"labels": {
"environment": "staging",
"service": "loadbalancer"
}
},
"spec": {
"running": True,
"template": {
"metadata": {
"labels": {
"environment": "staging",
"service": "loadbalancer"
}
},
"spec": {
"domain": {
"devices": {}
},
"terminationGracePeriodSeconds": 180
}
}
}
}
METADATA = '''apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: "testvm"
namespace: "default"
labels:
environment: staging
service: loadbalancer
spec:
running: True
template:
metadata:
labels:
environment: staging
service: loadbalancer
spec:
domain:
devices: {}
terminationGracePeriodSeconds: 180'''
FIXTURE2 = {
'name': 'testvm',
'namespace': 'default',
'state': 'present',
'labels': {
'service': 'loadbalancer',
'environment': 'staging'
},
'api_version': 'kubevirt.io/v1', 'running': True, 'termination_grace_period': 180, 'wait': False, 'wait_sleep': 5, 'wait_timeout': 120, 'force': False,
'generate_name': None, 'annotations': None, 'instancetype': None, 'preference': None, 'infer_from_volume': None, 'clear_revision_name': None,
'interfaces': None, 'networks': None, 'volumes': None, 'kubeconfig': None, 'context': None, 'host': None, 'api_key': None, 'username': None,
'password': None, 'validate_certs': None, 'ca_cert': None, 'client_cert': None, 'client_key': None, 'proxy': None, 'no_proxy': None, 'proxy_headers': None,
'persist_config': None, 'impersonate_user': None, 'impersonate_groups': None, 'delete_options': None,
'resource_definition': METADATA,
'wait_condition': {
'type': 'Ready',
'status': True
}
}
class TestCreateVM(unittest.TestCase):
def setUp(self):
self.mock_module_helper = patch.multiple(
basic.AnsibleModule,
exit_json=exit_json,
fail_json=fail_json
)
self.mock_module_helper.start()
self.mock_runner = patch.multiple(
runner,
get_api_client=get_api_client
)
self.mock_runner.start()
# Stop the patch after test execution
# like tearDown but executed also when the setup failed
self.addCleanup(self.mock_module_helper.stop)
self.addCleanup(self.mock_runner.stop)
def test_module_fail_when_required_args_missing(self):
with self.assertRaises(AnsibleFailJson):
set_module_args({})
kubevirt_vm.main()
def test_create(self):
set_module_args(
{
"name": "testvm",
"namespace": "default",
"state": "present",
"labels": {
"service": "loadbalancer",
"environment": "staging"
}
}
)
with patch.object(runner, "perform_action") as mock_run_command:
mock_run_command.return_value = (
{
"method": "create",
"changed": True,
"result": "success"
}
) # successful execution
with self.assertRaises(AnsibleExitJson) as result:
kubevirt_vm.main()
mock_run_command.assert_called_once_with(
ANY,
FIXTURE1,
FIXTURE2,
)

View File

@@ -0,0 +1,3 @@
pytest
PyYAML
kubernetes

View File

@@ -0,0 +1,51 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2021, Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
# This module maock the AnsibleModule class for more information please visite
# https://docs.ansible.com/ansible/latest/dev_guide/testing_units_modules.html#module-argument-processing
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import json
from ansible.module_utils import basic
from ansible.module_utils.common.text.converters import to_bytes
def set_module_args(args):
"""prepare arguments so that they will be picked up during module creation"""
args = json.dumps({"ANSIBLE_MODULE_ARGS": args})
basic._ANSIBLE_ARGS = to_bytes(args)
class AnsibleExitJson(Exception):
"""Exception class to be raised by module.exit_json and caught by the test case"""
pass
class AnsibleFailJson(Exception):
"""Exception class to be raised by module.fail_json and caught by the test case"""
pass
def exit_json(*args, **kwargs):
"""function to patch over exit_json; package return data into an exception"""
if "changed" not in kwargs:
kwargs["changed"] = False
raise AnsibleExitJson(kwargs)
def fail_json(*args, **kwargs):
"""function to patch over fail_json; package return data into an exception"""
kwargs["failed"] = True
raise AnsibleFailJson(kwargs)
def get_api_client(*args, **kwargs):
"""function to patch over get_api_client """
pass