Skip to content

Commit fd2da6d

Browse files
committed
ci: Add tft plan and workflow
This change is for running tests in Testing Farm CI. This is a replacement for BaseOS CI that we are currently using. Running it Testing Farm gives us more control. It adds a workflow for running tests, and a plans directory containing a test plan and a README-plans.md with some info. Note that this workflow runs from the main branch. This means that changes to the workflow must be merged to main, then pull requests will be able to run it. This is because the workflow uses on: issue_comment context, this is a security measure recommended by GitHub. It saves us from leaking organization secrets. The functionality is WIP, so await future fixes and updates. Signed-off-by: Sergei Petrosian <spetrosi@redhat.com>
1 parent afd82ac commit fd2da6d

File tree

8 files changed

+330
-2
lines changed

8 files changed

+330
-2
lines changed

Diff for: .fmf/version

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
1

Diff for: .github/workflows/tft.yml

+178
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
name: Run integration tests in Testing Farm
2+
on:
3+
issue_comment:
4+
types:
5+
- created
6+
permissions:
7+
contents: read
8+
# This is required for the ability to create/update the Pull request status
9+
statuses: write
10+
# The concurrency key is used to prevent multiple workflows from running at the same time
11+
concurrency:
12+
# group name contains reponame-pr_num to allow simualteneous runs in different PRs
13+
group: testing-farm-${{ github.event.repository.name }}-${{ github.event.issue.number }}
14+
cancel-in-progress: true
15+
jobs:
16+
prepare_vars:
17+
name: Get info from role and PR to determine if and how to test
18+
# Let's schedule tests only on user request. NOT automatically.
19+
# Only repository owner or member can schedule tests
20+
if: |
21+
github.event.issue.pull_request
22+
&& (contains(github.event.comment.body, '[citest]') || contains(github.event.comment.body, '[citest-all]'))
23+
&& (contains(fromJson('["OWNER", "MEMBER", "COLLABORATOR", "CONTRIBUTOR"]'), github.event.comment.author_association)
24+
|| contains('systemroller', github.event.comment.user.login))
25+
runs-on: ubuntu-latest
26+
outputs:
27+
supported_platforms: ${{ steps.supported_platforms.outputs.supported_platforms }}
28+
head_sha: ${{ steps.head_sha.outputs.head_sha }}
29+
datetime: ${{ steps.datetime.outputs.datetime }}
30+
memory: ${{ steps.memory.outputs.memory }}
31+
steps:
32+
33+
- name: Checkout repo
34+
uses: actions/checkout@v4
35+
36+
- name: Get head sha of the PR
37+
id: head_sha
38+
run: |
39+
head_sha=$(gh api "repos/$REPO/pulls/$PR_NO" --jq '.head.sha')
40+
echo "head_sha=$head_sha" >> $GITHUB_OUTPUT
41+
env:
42+
REPO: ${{ github.repository }}
43+
PR_NO: ${{ github.event.issue.number }}
44+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
45+
46+
- name: Get cuurent datetime
47+
id: datetime
48+
run: |
49+
printf -v datetime '%(%Y%m%d-%H%M%S)T' -1
50+
echo "datetime=$datetime" >> $GITHUB_OUTPUT
51+
52+
- name: Get memory
53+
id: memory
54+
run: |
55+
if [ -d tests/provision.fmf ]; then
56+
memory=$(grep -rPo ' m: \K(.*)' tests/provision.fmf)
57+
fi
58+
if [ -n "$memory" ]; then
59+
echo "memory=$memory" >> $GITHUB_OUTPUT
60+
else
61+
echo "memory=2048" >> $GITHUB_OUTPUT
62+
fi
63+
64+
- name: Get supported platforms
65+
id: supported_platforms
66+
run: |
67+
supported_platforms=""
68+
meta_main=meta/main.yml
69+
# All Fedora are supported, add latest Fedora versions to supported_platforms
70+
if yq '.galaxy_info.galaxy_tags[]' "$meta_main" | grep -qi fedora$; then
71+
supported_platforms+=" Fedora-39"
72+
supported_platforms+=" Fedora-40"
73+
fi
74+
# Specific Fedora versions supported
75+
if yq '.galaxy_info.galaxy_tags[]' "$meta_main" | grep -qiP 'fedora\d+$'; then
76+
for fedora_ver in $(yq '.galaxy_info.galaxy_tags[]' "$meta_main" | grep -iPo 'fedora\K(\d+$)'); do
77+
supported_platforms+=" Fedora-$fedora_ver"
78+
done
79+
fi
80+
if yq '.galaxy_info.galaxy_tags[]' "$meta_main" | grep -qi el7; then
81+
supported_platforms+=" CentOS-7-latest"
82+
fi
83+
for ver in 8 9 10; do
84+
if yq '.galaxy_info.galaxy_tags[]' "$meta_main" | grep -qi el"$ver"; then
85+
supported_platforms+=" CentOS-Stream-$ver"
86+
fi
87+
done
88+
echo "supported_platforms=$supported_platforms" >> $GITHUB_OUTPUT
89+
90+
testing-farm:
91+
name: ${{ matrix.platform }}/ansible-${{ matrix.ansible_version }}
92+
needs: prepare_vars
93+
strategy:
94+
fail-fast: false
95+
matrix:
96+
include:
97+
- platform: Fedora-39
98+
ansible_version: 2.17
99+
- platform: Fedora-40
100+
ansible_version: 2.17
101+
- platform: CentOS-7-latest
102+
ansible_version: 2.9
103+
- platform: CentOS-Stream-8
104+
ansible_version: 2.9
105+
# On CentOS-Stream-8, latest supported Ansible is 2.16
106+
- platform: CentOS-Stream-8
107+
ansible_version: 2.16
108+
- platform: CentOS-Stream-9
109+
ansible_version: 2.17
110+
- platform: CentOS-Stream-10
111+
ansible_version: 2.17
112+
runs-on: ubuntu-latest
113+
env:
114+
ARTIFACTS_DIR_NAME: "tf_${{ github.event.repository.name }}-${{ github.event.issue.number }}_\
115+
${{ matrix.platform }}-${{ matrix.ansible_version }}_\
116+
${{ needs.prepare_vars.outputs.datetime }}/artifacts"
117+
ARTIFACT_TARGET_DIR: /srv/pub/alt/linuxsystemroles/logs
118+
steps:
119+
- name: Set commit status as pending
120+
if: contains(needs.prepare_vars.outputs.supported_platforms, matrix.platform)
121+
uses: myrotvorets/set-commit-status-action@master
122+
with:
123+
sha: ${{ needs.prepare_vars.outputs.head_sha }}
124+
status: pending
125+
context: ${{ matrix.platform }}|ansible-${{ matrix.ansible_version }}
126+
description: Test started
127+
targetUrl: ""
128+
129+
- name: Set commit status as success with a description that platform is skipped
130+
if: "!contains(needs.prepare_vars.outputs.supported_platforms, matrix.platform)"
131+
uses: myrotvorets/set-commit-status-action@master
132+
with:
133+
sha: ${{ needs.prepare_vars.outputs.head_sha }}
134+
status: success
135+
context: ${{ matrix.platform }}|ansible-${{ matrix.ansible_version }}
136+
description: The role does not support this platform. Skipping.
137+
targetUrl: ""
138+
139+
- name: Run test in testing farm
140+
uses: sclorg/testing-farm-as-github-action@v2
141+
if: contains(needs.prepare_vars.outputs.supported_platforms, matrix.platform)
142+
env:
143+
ARTIFACTS_DIR: ${{ env.ARTIFACT_TARGET_DIR }}/${{ env.ARTIFACTS_DIR_NAME }}
144+
ARTIFACTS_URL: https://dl.fedoraproject.org/pub/alt/linuxsystemroles/logs/${{ env.ARTIFACTS_DIR_NAME }}
145+
with:
146+
git_url: ${{ github.server_url }}/${{ github.repository }}
147+
git_ref: ${{ needs.prepare_vars.outputs.head_sha }}
148+
pipeline_settings: '{ "type": "tmt-multihost" }'
149+
variables: "ANSIBLE_VER=${{ matrix.ansible_version }};\
150+
REPO_NAME=${{ github.event.repository.name }};\
151+
GITHUB_ORG=linux-system-roles;\
152+
PR_NUM=${{ github.event.issue.number }};\
153+
ARTIFACTS_DIR=${{ env.ARTIFACTS_DIR }};\
154+
ARTIFACTS_URL=${{ env.ARTIFACTS_URL }}"
155+
# Note that LINUXSYSTEMROLES_SSH_KEY must be single-line, TF doesn't read multi-line variables fine.
156+
secrets: "LINUXSYSTEMROLES_USER=${{ secrets.LINUXSYSTEMROLES_USER }};\
157+
LINUXSYSTEMROLES_DOMAIN=${{ secrets.LINUXSYSTEMROLES_DOMAIN }};\
158+
LINUXSYSTEMROLES_SSH_KEY=${{ secrets.LINUXSYSTEMROLES_SSH_KEY }}"
159+
compose: ${{ matrix.platform }}
160+
# There are two blockers for using public ranch:
161+
# 1. multihost is not supported in public https://github.com/teemtee/tmt/issues/2620
162+
# 2. Security issue that leaks long secrets - Jira TFT-2698
163+
tf_scope: private
164+
api_key: ${{ secrets.TF_API_KEY_RH }}
165+
update_pull_request_status: false
166+
tmt_hardware: '{ "memory": ">= ${{ needs.prepare_vars.outputs.memory }} MB" }'
167+
168+
- name: Set final commit status
169+
uses: myrotvorets/set-commit-status-action@master
170+
if: always() && contains(needs.prepare_vars.outputs.supported_platforms, matrix.platform)
171+
env:
172+
ARTIFACTS_URL: https://dl.fedoraproject.org/pub/alt/linuxsystemroles/logs/${{ env.ARTIFACTS_DIR_NAME }}
173+
with:
174+
sha: ${{ needs.prepare_vars.outputs.head_sha }}
175+
status: ${{ job.status }}
176+
context: ${{ matrix.platform }}|ansible-${{ matrix.ansible_version }}
177+
description: Test finished
178+
targetUrl: ${{ env.ARTIFACTS_URL }}

Diff for: README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# ha_cluster
22

3-
[![ansible-lint.yml](https://github.com/linux-system-roles/ha_cluster/actions/workflows/ansible-lint.yml/badge.svg)](https://github.com/linux-system-roles/ha_cluster/actions/workflows/ansible-lint.yml) [![ansible-test.yml](https://github.com/linux-system-roles/ha_cluster/actions/workflows/ansible-test.yml/badge.svg)](https://github.com/linux-system-roles/ha_cluster/actions/workflows/ansible-test.yml) [![codeql.yml](https://github.com/linux-system-roles/ha_cluster/actions/workflows/codeql.yml/badge.svg)](https://github.com/linux-system-roles/ha_cluster/actions/workflows/codeql.yml) [![markdownlint.yml](https://github.com/linux-system-roles/ha_cluster/actions/workflows/markdownlint.yml/badge.svg)](https://github.com/linux-system-roles/ha_cluster/actions/workflows/markdownlint.yml) [![python-unit-test.yml](https://github.com/linux-system-roles/ha_cluster/actions/workflows/python-unit-test.yml/badge.svg)](https://github.com/linux-system-roles/ha_cluster/actions/workflows/python-unit-test.yml) [![shellcheck.yml](https://github.com/linux-system-roles/ha_cluster/actions/workflows/shellcheck.yml/badge.svg)](https://github.com/linux-system-roles/ha_cluster/actions/workflows/shellcheck.yml) [![woke.yml](https://github.com/linux-system-roles/ha_cluster/actions/workflows/woke.yml/badge.svg)](https://github.com/linux-system-roles/ha_cluster/actions/workflows/woke.yml)
3+
[![ansible-lint.yml](https://github.com/linux-system-roles/ha_cluster/actions/workflows/ansible-lint.yml/badge.svg)](https://github.com/linux-system-roles/ha_cluster/actions/workflows/ansible-lint.yml) [![ansible-test.yml](https://github.com/linux-system-roles/ha_cluster/actions/workflows/ansible-test.yml/badge.svg)](https://github.com/linux-system-roles/ha_cluster/actions/workflows/ansible-test.yml) [![codeql.yml](https://github.com/linux-system-roles/ha_cluster/actions/workflows/codeql.yml/badge.svg)](https://github.com/linux-system-roles/ha_cluster/actions/workflows/codeql.yml) [![markdownlint.yml](https://github.com/linux-system-roles/ha_cluster/actions/workflows/markdownlint.yml/badge.svg)](https://github.com/linux-system-roles/ha_cluster/actions/workflows/markdownlint.yml) [![python-unit-test.yml](https://github.com/linux-system-roles/ha_cluster/actions/workflows/python-unit-test.yml/badge.svg)](https://github.com/linux-system-roles/ha_cluster/actions/workflows/python-unit-test.yml) [![shellcheck.yml](https://github.com/linux-system-roles/ha_cluster/actions/workflows/shellcheck.yml/badge.svg)](https://github.com/linux-system-roles/ha_cluster/actions/workflows/shellcheck.yml) [![tft.yml](https://github.com/linux-system-roles/ha_cluster/actions/workflows/tft.yml/badge.svg)](https://github.com/linux-system-roles/ha_cluster/actions/workflows/tft.yml) [![woke.yml](https://github.com/linux-system-roles/ha_cluster/actions/workflows/woke.yml/badge.svg)](https://github.com/linux-system-roles/ha_cluster/actions/workflows/woke.yml)
44

55
An Ansible role for managing High Availability Clustering.
66

Diff for: meta/main.yml

+5-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ galaxy_info:
1515
- "8"
1616
- "9"
1717
galaxy_tags:
18-
- hacluster
1918
- corosync
19+
- el8
20+
- el9
21+
- el10
22+
- fedora
23+
- hacluster
2024
- pacemaker
2125
dependencies: []

Diff for: plans/README-plans.md

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Introduction CI Testing Plans
2+
3+
Linux System Roles CI runs [tmt](https://tmt.readthedocs.io/en/stable/index.html) test plans in [Testing farm](https://docs.testing-farm.io/Testing%20Farm/0.1/index.html) with the [tmt.yml](https://github.com/linux-system-roles/ha_cluster/blob/main/.github/workflows/tmt.yml) GitHub workflow.
4+
5+
The plans/general.fmf plan is a test plan that is general for all roles. It does the following steps:
6+
7+
1. Provisions two machines, one used as an Ansible control node, and second used as a managed node.
8+
2. Does the required preparation on machines.
9+
3. For the given role and the given PR, runs the general test from [test.sh](https://github.com/linux-system-roles/tft-tests/blob/main/tests/general/test.sh).
10+
11+
The [tmt.yml](https://github.com/linux-system-roles/ha_cluster/blob/main/.github/workflows/tmt.yml) workflow runs the above plan and uploads the results to our Fedora storage for public access.
12+
This workflow uses Testing Farm's Github Action [Schedule tests on Testing Farm](https://github.com/marketplace/actions/schedule-tests-on-testing-farm).
13+
14+
## Running Tests
15+
16+
You can run tests locally with the `tmt try` cli.
17+
18+
### Prerequisites
19+
20+
* Install `tmt` as described in [Installation](https://tmt.readthedocs.io/en/stable/stories/install.html).
21+
22+
### Running Tests Locally
23+
24+
For now, this functionality requires you to push changes to a PR because the plan only runs from the main branch, or from the PR branch.
25+
So this is WIP.
26+
27+
To run tests locally, in the role repository, enter `tmt run plans --name plans/general <platform>`.
28+
Where `<platform>` is the name of the platform you want to run tests against.
29+
30+
For example, `tmt run plans --name plans/general Fedora-40`.
31+
32+
This command identifies the plans/general plan and provisions two machines, one used as an Ansible control node, and second used as a managed node.
33+
34+
You can also use `tmt try` to get to an interreactive prompt and be able to ssh into test machines.
35+
You must run `tmt try -p plans/general Fedora-40`, and the in the promt type `p` to prepare the machines, then `t` to run the tests.

Diff for: plans/general.fmf

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
summary: A general test for a system role
2+
provision:
3+
- name: control_node
4+
role: control_node
5+
# TF uses `how: artemis`, tmt try uses `how: virtual`. No need to define `how`
6+
# `connection: system` is for `how: virtual` to make VMs get a real IP to configure ssh easily
7+
# This setting is ignored on artemis so we can keep it
8+
connection: system
9+
- name: managed_node1
10+
role: managed_node
11+
connection: system
12+
environment:
13+
ANSIBLE_VER: 2.17
14+
REPO_NAME: ha_cluster
15+
PYTHON_VERSION: 3.12
16+
SYSTEM_ROLES_ONLY_TESTS: ""
17+
PR_NUM: ""
18+
prepare:
19+
- name: Use vault.centos.org repos (CS 7, 8 EOL workaround)
20+
script: |
21+
if grep -q -e 'CentOS Stream release 8' -e 'CentOS Linux release 7.9' /etc/redhat-release; then
22+
sed -i '/^mirror/d;s/#\(baseurl=http:\/\/\)mirror/\1vault/' /etc/yum.repos.d/*.repo
23+
fi
24+
25+
- name: Enable epel to install beakerlib on all platforms except CS10 and Fedora, there it's not available and not needed
26+
script: |
27+
if ! grep -q -e 'CentOS Stream release 10' -e 'Fedora release' /etc/redhat-release; then
28+
yum install epel-release -y
29+
fi
30+
where: control_node
31+
32+
- name: Additional steps to enable EPEL on EL 7
33+
script: |
34+
if grep -q 'CentOS Linux release 7.9' /etc/redhat-release; then
35+
yum install yum-utils -y
36+
yum-config-manager --enable epel epel-debuginfo epel-source
37+
fi
38+
where: control_node
39+
40+
- name: Install python on managed node when running CS8 with ansible!=2.9
41+
script: |
42+
if [ "$ANSIBLE_VER" != "2.9" ] && grep -q 'CentOS Stream release 8' /etc/redhat-release; then
43+
dnf install -y python"$PYTHON_VERSION"
44+
fi
45+
where: managed_node
46+
47+
- name: Distribute SSH keys when provisioned with how=virtual
48+
script: |
49+
if [ -f ${TMT_TREE%/*}/provision/control_node/id_ecdsa.pub ]; then
50+
cat ${TMT_TREE%/*}/provision/control_node/id_ecdsa.pub >> ~/.ssh/authorized_keys
51+
fi
52+
where: managed_node
53+
54+
discover:
55+
- name: Run test playbooks from control_node
56+
how: fmf
57+
url: https://github.com/linux-system-roles/tft-tests
58+
ref: main
59+
where: control_node
60+
filter: tag:test_playbooks
61+
execute:
62+
how: tmt

Diff for: vars/CentOS_10.yml

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# SPDX-License-Identifier: MIT
2+
---
3+
# Put internal variables here with CentOS 10 specific values.
4+
5+
# List of repositories holding HA cluster packages.
6+
# id: repo ID used to enable the repo
7+
# name: user-friendly name of a repo used to check if the repo is enabled
8+
__ha_cluster_repos:
9+
- id: highavailability
10+
name: HighAvailability
11+
- id: resilientstorage
12+
name: ResilientStorage
13+
14+
__ha_cluster_cloud_agents_packages:
15+
- resource-agents-cloud
16+
- fence-agents-aliyun
17+
- fence-agents-aws
18+
- fence-agents-azure-arm
19+
- fence-agents-compute
20+
- fence-agents-gce
21+
- fence-agents-ibm-powervs
22+
- fence-agents-ibm-vpc
23+
- fence-agents-kubevirt
24+
- fence-agents-openstack

Diff for: vars/RedHat_10.yml

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# SPDX-License-Identifier: MIT
2+
---
3+
# Put internal variables here with Red Hat Enterprise Linux 10 specific values.
4+
5+
# List of repositories holding HA cluster packages.
6+
# id: repo ID used to enable the repo
7+
# name: user-friendly name of a repo used to check if the repo is enabled
8+
__ha_cluster_repos:
9+
- id: rhel-10-for-{{ ansible_architecture }}-highavailability-rpms
10+
name: High Availability
11+
- id: rhel-10-for-{{ ansible_architecture }}-resilientstorage-rpms
12+
name: Resilient Storage
13+
14+
__ha_cluster_cloud_agents_packages:
15+
- resource-agents-cloud
16+
- fence-agents-aliyun
17+
- fence-agents-aws
18+
- fence-agents-azure-arm
19+
- fence-agents-compute
20+
- fence-agents-gce
21+
- fence-agents-ibm-powervs
22+
- fence-agents-ibm-vpc
23+
- fence-agents-kubevirt
24+
- fence-agents-openstack

0 commit comments

Comments
 (0)