├── .README.html
├── .ansible-lint
├── .codespell_ignores
├── .codespellrc
├── .commitlintrc.js
├── .fmf
└── version
├── .github
├── dependabot.yml
├── pull_request_template.md
└── workflows
│ ├── ansible-lint.yml
│ ├── ansible-managed-var-comment.yml
│ ├── ansible-test.yml
│ ├── build_docs.yml
│ ├── changelog_to_tag.yml
│ ├── codespell.yml
│ ├── markdownlint.yml
│ ├── pr-title-lint.yml
│ ├── qemu-kvm-integration-tests.yml
│ ├── shellcheck.yml
│ ├── test_converting_readme.yml
│ ├── tft.yml
│ ├── tft_citest_bad.yml
│ ├── weekly_ci.yml
│ └── woke.yml
├── .gitignore
├── .markdownlint.yaml
├── .ostree
├── README.md
├── get_ostree_data.sh
├── packages-runtime-CentOS-7.txt
├── packages-runtime-RedHat-6.txt
├── packages-runtime-RedHat-7.txt
├── packages-runtime.txt
├── packages-testing-CentOS-7.txt
├── packages-testing-RedHat-6.txt
├── packages-testing-RedHat-7.txt
└── packages-testing.txt
├── .pandoc_template.html5
├── .sanity-ansible-ignore-2.10.txt
├── .sanity-ansible-ignore-2.11.txt
├── .sanity-ansible-ignore-2.12.txt
├── .sanity-ansible-ignore-2.13.txt
├── .sanity-ansible-ignore-2.14.txt
├── .sanity-ansible-ignore-2.15.txt
├── .sanity-ansible-ignore-2.16.txt
├── .sanity-ansible-ignore-2.17.txt
├── .sanity-ansible-ignore-2.9.txt
├── .yamllint.yml
├── CHANGELOG.md
├── COPYING
├── README-ansible.md
├── README-ostree.md
├── README.md
├── ansible_pytest_extra_requirements.txt
├── contributing.md
├── custom_requirements.txt
├── defaults
└── main.yml
├── examples
├── multiple-ntp-servers.yml
└── single-pool.yml
├── handlers
└── main.yml
├── library
├── timesync_provider.sh
└── timesync_provider.yml
├── meta
├── collection-requirements.yml
└── main.yml
├── molecule
└── default
│ ├── Dockerfile.j2
│ └── molecule.yml
├── molecule_extra_requirements.txt
├── plans
├── README-plans.md
└── test_playbooks_parallel.fmf
├── pylint_extra_requirements.txt
├── pylintrc
├── pytest_extra_requirements.txt
├── tasks
├── main.yml
└── set_vars.yml
├── templates
├── chrony.conf.j2
├── chronyd.sysconfig.j2
├── ntp.conf.j2
├── ntpd.sysconfig.j2
├── phc2sys.sysconfig.j2
├── ptp4l.conf.j2
├── ptp4l.sysconfig.j2
└── timemaster.conf.j2
├── tests
├── .fmf
│ └── version
├── inventory.yaml.j2
├── provision.fmf
├── roles
│ └── linux-system-roles.timesync
│ │ ├── defaults
│ │ ├── handlers
│ │ ├── library
│ │ ├── meta
│ │ ├── tasks
│ │ ├── templates
│ │ └── vars
├── setup-snapshot.yml
├── tasks
│ ├── check_header.yml
│ ├── cleanup.yml
│ └── setup.yml
├── templates
│ └── get_ansible_managed.j2
├── tests_chrony.yml
├── tests_default.yml
├── tests_default_vars.yml
├── tests_default_wrapper.yml
├── tests_ntp.yml
├── tests_ntp_provider1.yml
├── tests_ntp_provider2.yml
├── tests_ntp_provider3.yml
├── tests_ntp_provider4.yml
├── tests_ntp_provider5.yml
├── tests_ntp_provider6.yml
├── tests_ntp_ptp.yml
├── tests_options.yml
├── tests_ptp_multi.yml
├── tests_ptp_single.yml
└── vars
│ └── rh_distros_vars.yml
├── tox.ini
└── vars
├── AlmaLinux_10.yml
├── AlmaLinux_8.yml
├── AlmaLinux_9.yml
├── CentOS_10.yml
├── CentOS_6.yml
├── CentOS_7.yml
├── CentOS_8.yml
├── CentOS_9.yml
├── Debian.yml
├── Fedora.yml
├── OracleLinux_10.yml
├── OracleLinux_6.yml
├── OracleLinux_7.yml
├── OracleLinux_8.yml
├── OracleLinux_9.yml
├── RedHat_10.yml
├── RedHat_6.yml
├── RedHat_7.yml
├── RedHat_8.yml
├── RedHat_9.yml
├── Rocky_10.yml
├── Rocky_8.yml
├── Rocky_9.yml
├── SL-Micro.yml
├── default.yml
└── main.yml
/.ansible-lint:
--------------------------------------------------------------------------------
1 | ---
2 | profile: production
3 | extra_vars:
4 | targets: target_hosts
5 | kinds:
6 | - yaml: "**/meta/collection-requirements.yml"
7 | - playbook: "**/tests/get_coverage.yml"
8 | - yaml: "**/tests/collection-requirements.yml"
9 | - playbook: "**/tests/tests_*.yml"
10 | - playbook: "**/tests/setup-snapshot.yml"
11 | - tasks: "**/tests/*.yml"
12 | - playbook: "**/tests/playbooks/*.yml"
13 | - tasks: "**/tests/tasks/*.yml"
14 | - tasks: "**/tests/tasks/*/*.yml"
15 | - vars: "**/tests/vars/*.yml"
16 | - playbook: "**/examples/*.yml"
17 | skip_list:
18 | - fqcn-builtins
19 | - var-naming[no-role-prefix]
20 | - sanity[cannot-ignore] # wokeignore:rule=sanity
21 | exclude_paths:
22 | - tests/roles/
23 | - .github/
24 | - .markdownlint.yaml
25 | - examples/roles/
26 | mock_roles:
27 | - linux-system-roles.timesync
28 | supported_ansible_also:
29 | - "2.14.0"
30 |
--------------------------------------------------------------------------------
/.codespell_ignores:
--------------------------------------------------------------------------------
1 | passt
2 |
--------------------------------------------------------------------------------
/.codespellrc:
--------------------------------------------------------------------------------
1 | [codespell]
2 | check-hidden = true
3 | # Note that `-w` doesn't work when ignore-multiline-regex is set
4 | # https://github.com/codespell-project/codespell/issues/3642
5 | ignore-multiline-regex = codespell:ignore-begin.*codespell:ignore-end
6 | ignore-words = .codespell_ignores
7 | # skip-file is not available https://github.com/codespell-project/codespell/pull/2759
8 | # .pandoc_template.html5 contains a typo in Licence that we shouldn't edit
9 | # .README.html is generated from README.md automatically - no need to check spelling
10 | skip = .pandoc_template.html5,.README.html
11 |
--------------------------------------------------------------------------------
/.commitlintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parserPreset: 'conventional-changelog-conventionalcommits',
3 | rules: {
4 | 'body-leading-blank': [1, 'always'],
5 | 'body-max-line-length': [2, 'always', 100],
6 | 'footer-leading-blank': [1, 'always'],
7 | 'footer-max-line-length': [2, 'always', 100],
8 | 'header-max-length': [2, 'always', 100],
9 | 'subject-case': [
10 | 2,
11 | 'never',
12 | ['start-case', 'pascal-case', 'upper-case'],
13 | ],
14 | 'subject-empty': [2, 'never'],
15 | 'subject-full-stop': [2, 'never', '.'],
16 | 'type-case': [2, 'always', 'lower-case'],
17 | 'type-empty': [2, 'never'],
18 | 'type-enum': [
19 | 2,
20 | 'always',
21 | [
22 | 'build',
23 | 'chore',
24 | 'ci',
25 | 'docs',
26 | 'feat',
27 | 'fix',
28 | 'perf',
29 | 'refactor',
30 | 'revert',
31 | 'style',
32 | 'test',
33 | 'tests',
34 | ],
35 | ],
36 | },
37 | prompt: {
38 | questions: {
39 | type: {
40 | description: "Select the type of change that you're committing",
41 | enum: {
42 | feat: {
43 | description: 'A new feature',
44 | title: 'Features',
45 | emoji: '✨',
46 | },
47 | fix: {
48 | description: 'A bug fix',
49 | title: 'Bug Fixes',
50 | emoji: '🐛',
51 | },
52 | docs: {
53 | description: 'Documentation only changes',
54 | title: 'Documentation',
55 | emoji: '📚',
56 | },
57 | style: {
58 | description:
59 | 'Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)',
60 | title: 'Styles',
61 | emoji: '💎',
62 | },
63 | refactor: {
64 | description:
65 | 'A code change that neither fixes a bug nor adds a feature',
66 | title: 'Code Refactoring',
67 | emoji: '📦',
68 | },
69 | perf: {
70 | description: 'A code change that improves performance',
71 | title: 'Performance Improvements',
72 | emoji: '🚀',
73 | },
74 | test: {
75 | description: 'Adding missing tests or correcting existing tests',
76 | title: 'Tests',
77 | emoji: '🚨',
78 | },
79 | tests: {
80 | description: 'Adding missing tests or correcting existing tests',
81 | title: 'Tests',
82 | emoji: '🚨',
83 | },
84 | build: {
85 | description:
86 | 'Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)',
87 | title: 'Builds',
88 | emoji: '🛠',
89 | },
90 | ci: {
91 | description:
92 | 'Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)',
93 | title: 'Continuous Integrations',
94 | emoji: '⚙️',
95 | },
96 | chore: {
97 | description: "Other changes that don't modify src or test files",
98 | title: 'Chores',
99 | emoji: '♻️',
100 | },
101 | revert: {
102 | description: 'Reverts a previous commit',
103 | title: 'Reverts',
104 | emoji: '🗑',
105 | },
106 | },
107 | },
108 | scope: {
109 | description:
110 | 'What is the scope of this change (e.g. component or file name)',
111 | },
112 | subject: {
113 | description:
114 | 'Write a short, imperative tense description of the change',
115 | },
116 | body: {
117 | description: 'Provide a longer description of the change',
118 | },
119 | isBreaking: {
120 | description: 'Are there any breaking changes?',
121 | },
122 | breakingBody: {
123 | description:
124 | 'A BREAKING CHANGE commit requires a body. Please enter a longer description of the commit itself',
125 | },
126 | breaking: {
127 | description: 'Describe the breaking changes',
128 | },
129 | isIssueAffected: {
130 | description: 'Does this change affect any open issues?',
131 | },
132 | issuesBody: {
133 | description:
134 | 'If issues are closed, the commit requires a body. Please enter a longer description of the commit itself',
135 | },
136 | issues: {
137 | description: 'Add issue references (e.g. "fix #123", "re #123".)',
138 | },
139 | },
140 | },
141 | };
142 |
--------------------------------------------------------------------------------
/.fmf/version:
--------------------------------------------------------------------------------
1 | 1
2 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | ---
2 | version: 2
3 | updates:
4 | - package-ecosystem: github-actions
5 | directory: /
6 | schedule:
7 | interval: monthly
8 | commit-message:
9 | prefix: ci
10 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | Enhancement:
2 |
3 | Reason:
4 |
5 | Result:
6 |
7 | Issue Tracker Tickets (Jira or BZ if any):
8 |
--------------------------------------------------------------------------------
/.github/workflows/ansible-lint.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Ansible Lint
3 | on: # yamllint disable-line rule:truthy
4 | pull_request:
5 | merge_group:
6 | branches:
7 | - main
8 | types:
9 | - checks_requested
10 | push:
11 | branches:
12 | - main
13 | workflow_dispatch:
14 | env:
15 | LSR_ROLE2COLL_NAMESPACE: fedora
16 | LSR_ROLE2COLL_NAME: linux_system_roles
17 | permissions:
18 | contents: read
19 | jobs:
20 | ansible_lint:
21 | runs-on: ubuntu-latest
22 | steps:
23 | - name: Update pip, git
24 | run: |
25 | set -euxo pipefail
26 | sudo apt update
27 | sudo apt install -y git
28 |
29 | - name: Checkout repo
30 | uses: actions/checkout@v4
31 |
32 | - name: Install tox, tox-lsr
33 | run: |
34 | set -euxo pipefail
35 | pip3 install "git+https://github.com/linux-system-roles/tox-lsr@3.11.0"
36 |
37 | - name: Convert role to collection format
38 | id: collection
39 | run: |
40 | set -euxo pipefail
41 | TOXENV=collection lsr_ci_runtox
42 | coll_dir=".tox/ansible_collections/$LSR_ROLE2COLL_NAMESPACE/$LSR_ROLE2COLL_NAME"
43 | # cleanup after collection conversion
44 | rm -rf "$coll_dir/.ansible" .tox/ansible-plugin-scan
45 | # ansible-lint action requires a .git directory???
46 | # https://github.com/ansible/ansible-lint/blob/main/action.yml#L45
47 | mkdir -p "$coll_dir/.git"
48 | meta_req_file="${{ github.workspace }}/meta/collection-requirements.yml"
49 | test_req_file="${{ github.workspace }}/tests/collection-requirements.yml"
50 | if [ -f "$meta_req_file" ] && [ -f "$test_req_file" ]; then
51 | coll_req_file="${{ github.workspace }}/req.yml"
52 | python -c 'import sys; import yaml
53 | hsh1 = yaml.safe_load(open(sys.argv[1]))
54 | hsh2 = yaml.safe_load(open(sys.argv[2]))
55 | coll = {}
56 | for item in hsh1["collections"] + hsh2["collections"]:
57 | if isinstance(item, dict):
58 | name = item["name"]
59 | rec = item
60 | else:
61 | name = item # assume string
62 | rec = {"name": name}
63 | if name not in coll:
64 | coll[name] = rec
65 | hsh1["collections"] = list(coll.values())
66 | yaml.safe_dump(hsh1, open(sys.argv[3], "w"))' "$meta_req_file" "$test_req_file" "$coll_req_file"
67 | echo merged "$coll_req_file"
68 | cat "$coll_req_file"
69 | elif [ -f "$meta_req_file" ]; then
70 | coll_req_file="$meta_req_file"
71 | elif [ -f "$test_req_file" ]; then
72 | coll_req_file="$test_req_file"
73 | else
74 | coll_req_file=""
75 | fi
76 | echo "coll_req_file=$coll_req_file" >> $GITHUB_OUTPUT
77 |
78 | - name: Run ansible-lint
79 | uses: ansible/ansible-lint@v25
80 | with:
81 | working_directory: ${{ github.workspace }}/.tox/ansible_collections/${{ env.LSR_ROLE2COLL_NAMESPACE }}/${{ env.LSR_ROLE2COLL_NAME }}
82 | requirements_file: ${{ steps.collection.outputs.coll_req_file }}
83 | env:
84 | ANSIBLE_COLLECTIONS_PATH: ${{ github.workspace }}/.tox
85 |
--------------------------------------------------------------------------------
/.github/workflows/ansible-managed-var-comment.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Check for ansible_managed variable use in comments
3 | on: # yamllint disable-line rule:truthy
4 | pull_request:
5 | merge_group:
6 | branches:
7 | - main
8 | types:
9 | - checks_requested
10 | push:
11 | branches:
12 | - main
13 | workflow_dispatch:
14 | permissions:
15 | contents: read
16 | jobs:
17 | ansible_managed_var_comment:
18 | runs-on: ubuntu-latest
19 | steps:
20 | - name: Update pip, git
21 | run: |
22 | set -euxo pipefail
23 | python3 -m pip install --upgrade pip
24 | sudo apt update
25 | sudo apt install -y git
26 |
27 | - name: Checkout repo
28 | uses: actions/checkout@v4
29 |
30 | - name: Install tox, tox-lsr
31 | run: |
32 | set -euxo pipefail
33 | pip3 install "git+https://github.com/linux-system-roles/tox-lsr@3.11.0"
34 |
35 | - name: Run ansible-plugin-scan
36 | run: |
37 | set -euxo pipefail
38 | TOXENV=ansible-managed-var-comment lsr_ci_runtox
39 |
--------------------------------------------------------------------------------
/.github/workflows/ansible-test.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Ansible Test
3 | on: # yamllint disable-line rule:truthy
4 | pull_request:
5 | merge_group:
6 | branches:
7 | - main
8 | types:
9 | - checks_requested
10 | push:
11 | branches:
12 | - main
13 | workflow_dispatch:
14 | env:
15 | LSR_ROLE2COLL_NAMESPACE: fedora
16 | LSR_ROLE2COLL_NAME: linux_system_roles
17 | permissions:
18 | contents: read
19 | jobs:
20 | ansible_test:
21 | runs-on: ubuntu-latest
22 | steps:
23 | - name: Update pip, git
24 | run: |
25 | set -euxo pipefail
26 | python3 -m pip install --upgrade pip
27 | sudo apt update
28 | sudo apt install -y git
29 |
30 | - name: Checkout repo
31 | uses: actions/checkout@v4
32 |
33 | - name: Install tox, tox-lsr
34 | run: |
35 | set -euxo pipefail
36 | pip3 install "git+https://github.com/linux-system-roles/tox-lsr@3.11.0"
37 |
38 | - name: Convert role to collection format
39 | run: |
40 | set -euxo pipefail
41 | TOXENV=collection lsr_ci_runtox
42 |
43 | - name: Run ansible-test
44 | uses: ansible-community/ansible-test-gh-action@release/v1
45 | with:
46 | testing-type: sanity # wokeignore:rule=sanity
47 | ansible-core-version: stable-2.17
48 | collection-src-directory: ${{ github.workspace }}/.tox/ansible_collections/${{ env.LSR_ROLE2COLL_NAMESPACE }}/${{ env.LSR_ROLE2COLL_NAME }}
49 |
--------------------------------------------------------------------------------
/.github/workflows/build_docs.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # yamllint disable rule:line-length
3 | name: Convert README.md to HTML and push to docs branch
4 | on: # yamllint disable-line rule:truthy
5 | push:
6 | branches:
7 | - main
8 | paths:
9 | - README.md
10 | release:
11 | types:
12 | - published
13 | permissions:
14 | contents: read
15 | jobs:
16 | build_docs:
17 | runs-on: ubuntu-latest
18 | permissions:
19 | contents: write
20 | steps:
21 | - name: Update pip, git
22 | run: |
23 | set -euxo pipefail
24 | sudo apt update
25 | sudo apt install -y git
26 |
27 | - name: Check out code
28 | uses: actions/checkout@v4
29 | with:
30 | fetch-depth: 0
31 | - name: Ensure the docs branch
32 | run: |
33 | set -euxo pipefail
34 | branch=docs
35 | existed_in_remote=$(git ls-remote --heads origin $branch)
36 |
37 | if [ -z "${existed_in_remote}" ]; then
38 | echo "Creating $branch branch"
39 | git config --global user.name "${{ github.actor }}"
40 | git config --global user.email "${{ github.actor }}@users.noreply.github.com"
41 | git checkout --orphan $branch
42 | git reset --hard
43 | git commit --allow-empty -m "Initializing $branch branch"
44 | git push origin $branch
45 | echo "Created $branch branch"
46 | else
47 | echo "Branch $branch already exists"
48 | fi
49 |
50 | - name: Checkout the docs branch
51 | uses: actions/checkout@v4
52 | with:
53 | ref: docs
54 |
55 | - name: Fetch README.md and .pandoc_template.html5 template from the workflow branch
56 | uses: actions/checkout@v4
57 | with:
58 | sparse-checkout: |
59 | README.md
60 | .pandoc_template.html5
61 | sparse-checkout-cone-mode: false
62 | path: ref_branch
63 | - name: Set RELEASE_VERSION based on whether run on release or on push
64 | run: |
65 | set -euxo pipefail
66 | if [ ${{ github.event_name }} = release ]; then
67 | echo "RELEASE_VERSION=${{ github.event.release.tag_name }}" >> $GITHUB_ENV
68 | elif [ ${{ github.event_name }} = push ]; then
69 | echo "RELEASE_VERSION=latest" >> $GITHUB_ENV
70 | else
71 | echo Unsupported event
72 | exit 1
73 | fi
74 |
75 | - name: Ensure that version and docs directories exist
76 | run: mkdir -p ${{ env.RELEASE_VERSION }} docs
77 |
78 | - name: Remove badges from README.md prior to converting to HTML
79 | run: sed -i '1,8 {/^\[\!.*actions\/workflows/d}' ref_branch/README.md
80 |
81 | - name: Convert README.md to HTML and save to the version directory
82 | uses: docker://pandoc/core:latest
83 | with:
84 | args: >-
85 | --from gfm --to html5 --toc --shift-heading-level-by=-1
86 | --template ref_branch/.pandoc_template.html5
87 | --output ${{ env.RELEASE_VERSION }}/README.html ref_branch/README.md
88 |
89 | - name: Copy latest README.html to docs/index.html for GitHub pages
90 | if: env.RELEASE_VERSION == 'latest'
91 | run: cp ${{ env.RELEASE_VERSION }}/README.html docs/index.html
92 |
93 | - name: Upload README.html as an artifact
94 | uses: actions/upload-artifact@master
95 | with:
96 | name: README.html
97 | path: ${{ env.RELEASE_VERSION }}/README.html
98 |
99 | - name: Commit changes
100 | run: |
101 | git config --global user.name "${{ github.actor }}"
102 | git config --global user.email "${{ github.actor }}@users.noreply.github.com"
103 | git add ${{ env.RELEASE_VERSION }}/README.html docs/index.html
104 | git commit -m "Update README.html for ${{ env.RELEASE_VERSION }}"
105 |
106 | - name: Push changes
107 | uses: ad-m/github-push-action@master
108 | with:
109 | github_token: ${{ secrets.GITHUB_TOKEN }}
110 | branch: docs
111 |
--------------------------------------------------------------------------------
/.github/workflows/changelog_to_tag.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # yamllint disable rule:line-length
3 | name: Tag, release, and publish role based on CHANGELOG.md push
4 | on: # yamllint disable-line rule:truthy
5 | push:
6 | branches:
7 | - main
8 | paths:
9 | - CHANGELOG.md
10 | permissions:
11 | contents: read
12 | jobs:
13 | tag_release_publish:
14 | runs-on: ubuntu-latest
15 | permissions:
16 | contents: write
17 | steps:
18 | - name: Update pip, git
19 | run: |
20 | set -euxo pipefail
21 | sudo apt update
22 | sudo apt install -y git
23 |
24 | - name: checkout PR
25 | uses: actions/checkout@v4
26 |
27 | - name: Get tag and message from the latest CHANGELOG.md commit
28 | id: tag
29 | run: |
30 | set -euxo pipefail
31 | print=false
32 | while read -r line; do
33 | if [[ "$line" =~ ^\[([0-9]+\.[0-9]+\.[0-9]+)\]\ -\ [0-9-]+ ]]; then
34 | if [ "$print" = false ]; then
35 | _tagname="${BASH_REMATCH[1]}"
36 | echo "$line"
37 | print=true
38 | else
39 | break
40 | fi
41 | elif [ "$print" = true ]; then
42 | echo "$line"
43 | fi
44 | done < CHANGELOG.md > ./.tagmsg.txt
45 | git fetch --all --tags
46 | for t in $( git tag -l ); do
47 | if [ "$t" = "$_tagname" ]; then
48 | echo INFO: tag "$t" already exists
49 | exit 1
50 | fi
51 | done
52 | # Get name of the branch that the change was pushed to
53 | _branch="${GITHUB_REF_NAME:-}"
54 | if [ "$_branch" = master ] || [ "$_branch" = main ]; then
55 | echo Using branch name ["$_branch"] as push branch
56 | else
57 | echo WARNING: GITHUB_REF_NAME ["$_branch"] is not main or master
58 | _branch=$( git branch -r | grep -o 'origin/HEAD -> origin/.*$' | \
59 | awk -F'/' '{print $3}' || : )
60 | fi
61 | if [ -z "$_branch" ]; then
62 | _branch=$( git branch --points-at HEAD --no-color --format='%(refname:short)' )
63 | fi
64 | if [ -z "$_branch" ]; then
65 | echo ERROR: unable to determine push branch
66 | git branch -a
67 | exit 1
68 | fi
69 | echo "tagname=$_tagname" >> "$GITHUB_OUTPUT"
70 | echo "branch=$_branch" >> "$GITHUB_OUTPUT"
71 | - name: Create tag
72 | uses: mathieudutour/github-tag-action@v6.2
73 | with:
74 | github_token: ${{ secrets.GITHUB_TOKEN }}
75 | custom_tag: ${{ steps.tag.outputs.tagname }}
76 | tag_prefix: ''
77 |
78 | - name: Create Release
79 | id: create_release
80 | uses: ncipollo/release-action@v1
81 | with:
82 | tag: ${{ steps.tag.outputs.tagname }}
83 | name: Version ${{ steps.tag.outputs.tagname }}
84 | bodyFile: ./.tagmsg.txt
85 | makeLatest: true
86 |
87 | - name: Publish role to Galaxy
88 | uses: robertdebock/galaxy-action@1.2.1
89 | with:
90 | galaxy_api_key: ${{ secrets.galaxy_api_key }}
91 | git_branch: ${{ steps.tag.outputs.branch }}
92 |
--------------------------------------------------------------------------------
/.github/workflows/codespell.yml:
--------------------------------------------------------------------------------
1 | # Codespell configuration is within .codespellrc
2 | ---
3 | name: Codespell
4 | on: # yamllint disable-line rule:truthy
5 | - pull_request
6 | permissions:
7 | contents: read
8 | jobs:
9 | codespell:
10 | name: Check for spelling errors
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: Checkout
14 | uses: actions/checkout@v4
15 |
16 | - name: Codespell
17 | uses: codespell-project/actions-codespell@v2
18 |
--------------------------------------------------------------------------------
/.github/workflows/markdownlint.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # yamllint disable rule:line-length
3 | name: Markdown Lint
4 | on: # yamllint disable-line rule:truthy
5 | pull_request:
6 | merge_group:
7 | branches:
8 | - main
9 | types:
10 | - checks_requested
11 | push:
12 | branches:
13 | - main
14 | workflow_dispatch:
15 | permissions:
16 | contents: read
17 | jobs:
18 | markdownlint:
19 | runs-on: ubuntu-latest
20 | steps:
21 | - name: Update pip, git
22 | run: |
23 | set -euxo pipefail
24 | sudo apt update
25 | sudo apt install -y git
26 |
27 | - name: Check out code
28 | uses: actions/checkout@v4
29 |
30 | # CHANGELOG.md is generated automatically from PR titles and descriptions
31 | # It might have issues but they are not critical
32 | - name: Lint all markdown files except for CHANGELOG.md
33 | uses: docker://avtodev/markdown-lint:master
34 | with:
35 | args: >-
36 | --ignore=CHANGELOG.md
37 | **/*.md
38 | config: .markdownlint.yaml
39 |
--------------------------------------------------------------------------------
/.github/workflows/pr-title-lint.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: PR Title Lint
3 | on: # yamllint disable-line rule:truthy
4 | pull_request:
5 | types:
6 | - opened
7 | - synchronize
8 | - reopened
9 | - edited
10 | merge_group:
11 | branches:
12 | - main
13 | types:
14 | - checks_requested
15 | permissions:
16 | contents: read
17 | jobs:
18 | commit-checks:
19 | runs-on: ubuntu-latest
20 | steps:
21 | - uses: actions/checkout@v4
22 | with:
23 | fetch-depth: 0
24 |
25 | - name: Install conventional-commit linter
26 | run: npm install @commitlint/config-conventional @commitlint/cli
27 |
28 | - name: Run commitlint on PR title
29 | env:
30 | PR_TITLE: ${{ github.event.pull_request.title }}
31 | # Echo from env variable to avoid bash errors with extra characters
32 | run: echo "$PR_TITLE" | npx commitlint --verbose
33 |
--------------------------------------------------------------------------------
/.github/workflows/qemu-kvm-integration-tests.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Test
3 | on: # yamllint disable-line rule:truthy
4 | pull_request:
5 | merge_group:
6 | branches:
7 | - main
8 | types:
9 | - checks_requested
10 | push:
11 | branches:
12 | - main
13 | workflow_dispatch:
14 |
15 | permissions:
16 | contents: read
17 | # This is required for the ability to create/update the Pull request status
18 | statuses: write
19 | jobs:
20 | scenario:
21 | runs-on: ubuntu-latest
22 |
23 | strategy:
24 | fail-fast: false
25 | matrix:
26 | scenario:
27 | # QEMU
28 | - { image: "centos-9", env: "qemu-ansible-core-2.16" }
29 | - { image: "centos-10", env: "qemu-ansible-core-2.17" }
30 | # ansible/libdnf5 bug: https://issues.redhat.com/browse/RHELMISC-10110
31 | # - { image: "fedora-41", env: "qemu-ansible-core-2.17" }
32 | - { image: "fedora-42", env: "qemu-ansible-core-2.19" }
33 |
34 | # container
35 | - { image: "centos-9", env: "container-ansible-core-2.16" }
36 | - { image: "centos-9-bootc", env: "container-ansible-core-2.16" }
37 | # broken on non-running dbus
38 | # - { image: "centos-10", env: "container-ansible-core-2.17" }
39 | - { image: "centos-10-bootc", env: "container-ansible-core-2.17" }
40 | - { image: "fedora-41", env: "container-ansible-core-2.17" }
41 | - { image: "fedora-42", env: "container-ansible-core-2.17" }
42 | - { image: "fedora-41-bootc", env: "container-ansible-core-2.17" }
43 | - { image: "fedora-42-bootc", env: "container-ansible-core-2.17" }
44 |
45 | env:
46 | TOX_ARGS: "--skip-tags tests::infiniband,tests::nvme,tests::scsi"
47 |
48 | steps:
49 | - name: Checkout repo
50 | uses: actions/checkout@v4
51 |
52 | - name: Check if platform is supported
53 | id: check_platform
54 | run: |
55 | set -euxo pipefail
56 | image="${{ matrix.scenario.image }}"
57 | image="${image%-bootc}"
58 |
59 | # convert image to tag formats
60 | platform=
61 | platform_version=
62 | case "$image" in
63 | centos-*) platform=el; platform_version=el"${image#centos-}" ;;
64 | fedora-*) platform=fedora; platform_version="${image/-/}" ;;
65 | esac
66 | supported=
67 | if yq -e '.galaxy_info.galaxy_tags[] | select(. == "'${platform_version}'" or . == "'${platform}'")' meta/main.yml; then
68 | supported=true
69 | fi
70 |
71 | # bootc build support (in buildah) has a separate flag
72 | if [ "${{ matrix.scenario.image }}" != "$image" ]; then
73 | if ! yq -e '.galaxy_info.galaxy_tags[] | select(. == "containerbuild")' meta/main.yml; then
74 | supported=
75 | fi
76 | else
77 | # roles need to opt into support for running in a system container
78 | env="${{ matrix.scenario.env }}"
79 | if [ "${env#container}" != "$env" ] &&
80 | ! yq -e '.galaxy_info.galaxy_tags[] | select(. == "container")' meta/main.yml; then
81 | supported=
82 | fi
83 | fi
84 |
85 | echo "supported=$supported" >> "$GITHUB_OUTPUT"
86 |
87 | - name: Set up /dev/kvm
88 | if: steps.check_platform.outputs.supported
89 | run: |
90 | echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm.rules
91 | sudo udevadm control --reload-rules
92 | sudo udevadm trigger --name-match=kvm --settle
93 | ls -l /dev/kvm
94 |
95 | - name: Disable man-db to speed up package install
96 | if: steps.check_platform.outputs.supported
97 | run: |
98 | echo "set man-db/auto-update false" | sudo debconf-communicate
99 | sudo dpkg-reconfigure man-db
100 |
101 | - name: Install test dependencies
102 | if: steps.check_platform.outputs.supported
103 | run: |
104 | set -euxo pipefail
105 | python3 -m pip install --upgrade pip
106 | sudo apt update
107 | sudo apt install -y --no-install-recommends git ansible-core genisoimage qemu-system-x86
108 | pip3 install "git+https://github.com/linux-system-roles/tox-lsr@3.11.0"
109 |
110 | # HACK: Drop this when moving this workflow to 26.04 LTS
111 | - name: Update podman to 5.x for compatibility with bootc-image-builder's podman 5
112 | if: steps.check_platform.outputs.supported && endsWith(matrix.scenario.image, '-bootc')
113 | run: |
114 | sed 's/noble/plucky/g' /etc/apt/sources.list.d/ubuntu.sources | sudo tee /etc/apt/sources.list.d/plucky.sources >/dev/null
115 | cat </dev/null
116 | Package: podman buildah golang-github-containers-common crun libgpgme11t64 libgpg-error0 golang-github-containers-image catatonit conmon containers-storage
117 | Pin: release n=plucky
118 | Pin-Priority: 991
119 |
120 | Package: libsubid4 netavark passt aardvark-dns containernetworking-plugins libslirp0 slirp4netns
121 | Pin: release n=plucky
122 | Pin-Priority: 991
123 |
124 | Package: *
125 | Pin: release n=plucky
126 | Pin-Priority: 400
127 | EOF
128 |
129 | sudo apt update
130 | sudo apt install -y podman crun conmon containers-storage
131 |
132 | - name: Configure tox-lsr
133 | if: steps.check_platform.outputs.supported
134 | run: >-
135 | curl -o ~/.config/linux-system-roles.json
136 | https://raw.githubusercontent.com/linux-system-roles/linux-system-roles.github.io/master/download/linux-system-roles.json
137 |
138 | - name: Run qemu integration tests
139 | if: steps.check_platform.outputs.supported && startsWith(matrix.scenario.env, 'qemu')
140 | run: >-
141 | tox -e ${{ matrix.scenario.env }} -- --image-name ${{ matrix.scenario.image }} --make-batch
142 | --log-level debug $TOX_ARGS --skip-tags tests::bootc-e2e
143 | --lsr-report-errors-url DEFAULT --
144 |
145 | - name: Qemu result summary
146 | if: steps.check_platform.outputs.supported && startsWith(matrix.scenario.env, 'qemu') && always()
147 | run: |
148 | set -euo pipefail
149 | # some platforms may have setup/cleanup playbooks - need to find the
150 | # actual test playbook that starts with tests_
151 | while read code start end test_files; do
152 | for f in $test_files; do
153 | test_file="$f"
154 | f="$(basename $test_file)"
155 | if [[ "$f" =~ ^tests_ ]]; then
156 | break
157 | fi
158 | done
159 | if [ "$code" = "0" ]; then
160 | echo -n "PASS: "
161 | mv "$test_file.log" "${test_file}-SUCCESS.log"
162 | else
163 | echo -n "FAIL: "
164 | mv "$test_file.log" "${test_file}-FAIL.log"
165 | fi
166 | echo "$f"
167 | done < batch.report
168 |
169 | - name: Run container tox integration tests
170 | if: steps.check_platform.outputs.supported && startsWith(matrix.scenario.env, 'container')
171 | run: |
172 | set -euo pipefail
173 | # HACK: debug.py/profile.py setup is broken
174 | export LSR_CONTAINER_PROFILE=false
175 | export LSR_CONTAINER_PRETTY=false
176 | rc=0
177 | for t in tests/tests_*.yml; do
178 | if tox -e ${{ matrix.scenario.env }} -- --image-name ${{ matrix.scenario.image }} $t > ${t}.log 2>&1; then
179 | echo "PASS: $(basename $t)"
180 | mv "${t}.log" "${t}-SUCCESS.log"
181 | else
182 | echo "FAIL: $(basename $t)"
183 | mv "${t}.log" "${t}-FAIL.log"
184 | rc=1
185 | fi
186 | done
187 | exit $rc
188 |
189 | - name: Run bootc validation tests in QEMU
190 | if: steps.check_platform.outputs.supported &&
191 | startsWith(matrix.scenario.env, 'container') &&
192 | endsWith(matrix.scenario.image, '-bootc')
193 | run: |
194 | set -euxo pipefail
195 | env=$(echo "${{ matrix.scenario.env }}" | sed 's/^container-/qemu-/')
196 |
197 | for image_file in $(ls tests/tmp/*/qcow2/disk.qcow2 2>/dev/null); do
198 | test="tests/$(basename $(dirname $(dirname $image_file))).yml"
199 | if tox -e "$env" -- --image-file "$(pwd)/$image_file" \
200 | --log-level debug $TOX_ARGS \
201 | --lsr-report-errors-url DEFAULT \
202 | -e __bootc_validation=true \
203 | -- "$test" >out 2>&1; then
204 | mv out "${test}-PASS.log"
205 | else
206 | mv out "${test}-FAIL.log"
207 | exit 1
208 | fi
209 | done
210 |
211 | - name: Upload test logs on failure
212 | if: failure()
213 | uses: actions/upload-artifact@v4
214 | with:
215 | name: "logs-${{ matrix.scenario.image }}-${{ matrix.scenario.env }}"
216 | path: |
217 | tests/*.log
218 | artifacts/default_provisioners.log
219 | artifacts/*.qcow2.*.log
220 | batch.txt
221 | batch.report
222 | retention-days: 30
223 |
224 | - name: Show test log failures
225 | if: steps.check_platform.outputs.supported && failure()
226 | run: |
227 | set -euo pipefail
228 | # grab check_logs.py script
229 | curl -s -L -o check_logs.py https://raw.githubusercontent.com/linux-system-roles/auto-maintenance/refs/heads/main/check_logs.py
230 | chmod +x check_logs.py
231 | declare -a cmdline=(./check_logs.py --github-action-format)
232 | for log in tests/*-FAIL.log; do
233 | cmdline+=(--lsr-error-log "$log")
234 | done
235 | "${cmdline[@]}"
236 |
237 | - name: Set commit status as success with a description that platform is skipped
238 | if: ${{ steps.check_platform.outputs.supported == '' }}
239 | uses: myrotvorets/set-commit-status-action@master
240 | with:
241 | status: success
242 | context: "${{ github.workflow }} / scenario (${{ matrix.scenario.image }}, ${{ matrix.scenario.env }}) (pull_request)"
243 | description: The role does not support this platform. Skipping.
244 | targetUrl: ""
245 |
--------------------------------------------------------------------------------
/.github/workflows/shellcheck.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: ShellCheck
3 | on: # yamllint disable-line rule:truthy
4 | pull_request:
5 | merge_group:
6 | branches:
7 | - main
8 | types:
9 | - checks_requested
10 | push:
11 | branches:
12 | - main
13 | workflow_dispatch:
14 | env:
15 | # some scripts source tox-lsr scripts - suppress that check
16 | SHELLCHECK_OPTS: -e SC1091
17 | permissions:
18 | contents: read
19 | jobs:
20 | shellcheck:
21 | runs-on: ubuntu-latest
22 | steps:
23 | - name: Update git
24 | run: |
25 | set -euxo pipefail
26 | sudo apt update
27 | sudo apt install -y git
28 |
29 | - name: Checkout repo
30 | uses: actions/checkout@v4
31 |
32 | - name: Run ShellCheck
33 | id: shellcheck_id
34 | uses: ludeeus/action-shellcheck@master
35 |
36 | - name: Show file paths scanned
37 | run: |
38 | echo Files scanned:
39 | echo "${{ steps.shellcheck_id.outputs.files }}"
40 |
--------------------------------------------------------------------------------
/.github/workflows/test_converting_readme.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # yamllint disable rule:line-length
3 | name: Test converting README.md to README.html
4 | on: # yamllint disable-line rule:truthy
5 | pull_request:
6 | merge_group:
7 | branches:
8 | - main
9 | types:
10 | - checks_requested
11 | push:
12 | branches:
13 | - main
14 | permissions:
15 | contents: read
16 | jobs:
17 | test_converting_readme:
18 | runs-on: ubuntu-latest
19 | permissions:
20 | contents: write
21 | steps:
22 | - name: Update pip, git
23 | run: |
24 | set -euxo pipefail
25 | sudo apt update
26 | sudo apt install -y git
27 |
28 | - name: Check out code
29 | uses: actions/checkout@v4
30 |
31 | - name: Remove badges from README.md prior to converting to HTML
32 | run: sed -i '1,8 {/^\[\!.*actions\/workflows/d}' README.md
33 |
34 | - name: Convert README.md to HTML
35 | uses: docker://pandoc/core:latest
36 | with:
37 | args: >-
38 | --from gfm --to html5 --toc --shift-heading-level-by=-1
39 | --template .pandoc_template.html5
40 | --output README.html README.md
41 |
42 | - name: Upload README.html as an artifact
43 | uses: actions/upload-artifact@master
44 | with:
45 | name: README.html
46 | path: README.html
47 |
--------------------------------------------------------------------------------
/.github/workflows/tft.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Run integration tests in Testing Farm
3 | on:
4 | issue_comment:
5 | types:
6 | - created
7 | permissions:
8 | contents: read
9 | # This is required for the ability to create/update the Pull request status
10 | statuses: write
11 | jobs:
12 | prepare_vars:
13 | name: Get info from role and PR to determine if and how to test
14 | # The concurrency key is used to prevent multiple workflows from running at the same time
15 | concurrency:
16 | # group name contains reponame-pr_num to allow simualteneous runs in different PRs
17 | group: testing-farm-${{ github.event.repository.name }}-${{ github.event.issue.number }}
18 | cancel-in-progress: true
19 | # Let's schedule tests only on user request. NOT automatically.
20 | # Only repository owner or member can schedule tests
21 | if: |
22 | github.event.issue.pull_request
23 | && contains(github.event.comment.body, '[citest]')
24 | && (contains(fromJson('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)
25 | || contains('systemroller', github.event.comment.user.login))
26 | runs-on: ubuntu-latest
27 | outputs:
28 | supported_platforms: ${{ steps.supported_platforms.outputs.supported_platforms }}
29 | head_sha: ${{ steps.head_sha.outputs.head_sha }}
30 | memory: ${{ steps.memory.outputs.memory }}
31 | steps:
32 | - name: Dump github context
33 | run: echo "$GITHUB_CONTEXT"
34 | shell: bash
35 | env:
36 | GITHUB_CONTEXT: ${{ toJson(github) }}
37 |
38 | - name: Checkout repo
39 | uses: actions/checkout@v4
40 |
41 | - name: Get head sha of the PR
42 | id: head_sha
43 | run: |
44 | head_sha=$(gh api "repos/$REPO/pulls/$PR_NO" --jq '.head.sha')
45 | echo "head_sha=$head_sha" >> $GITHUB_OUTPUT
46 | env:
47 | REPO: ${{ github.repository }}
48 | PR_NO: ${{ github.event.issue.number }}
49 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
50 |
51 | - name: Checkout PR
52 | uses: actions/checkout@v4
53 | with:
54 | ref: ${{ steps.head_sha.outputs.head_sha }}
55 |
56 | - name: Get memory
57 | id: memory
58 | run: |
59 | if [ -d tests/provision.fmf ]; then
60 | memory=$(grep -rPo ' m: \K(.*)' tests/provision.fmf)
61 | fi
62 | if [ -n "$memory" ]; then
63 | echo "memory=$memory" >> $GITHUB_OUTPUT
64 | else
65 | echo "memory=2048" >> $GITHUB_OUTPUT
66 | fi
67 |
68 | - name: Get supported platforms
69 | id: supported_platforms
70 | run: |
71 | supported_platforms=""
72 | meta_main=meta/main.yml
73 | # All Fedora are supported, add latest Fedora versions to supported_platforms
74 | if yq '.galaxy_info.galaxy_tags[]' "$meta_main" | grep -qi fedora$; then
75 | supported_platforms+=" Fedora-41"
76 | supported_platforms+=" Fedora-42"
77 | fi
78 | # Specific Fedora versions supported
79 | if yq '.galaxy_info.galaxy_tags[]' "$meta_main" | grep -qiP 'fedora\d+$'; then
80 | for fedora_ver in $(yq '.galaxy_info.galaxy_tags[]' "$meta_main" | grep -iPo 'fedora\K(\d+$)'); do
81 | supported_platforms+=" Fedora-$fedora_ver"
82 | done
83 | fi
84 | if yq '.galaxy_info.galaxy_tags[]' "$meta_main" | grep -qi el7; then
85 | supported_platforms+=" CentOS-7-latest"
86 | fi
87 | for ver in 8 9 10; do
88 | if yq '.galaxy_info.galaxy_tags[]' "$meta_main" | grep -qi el"$ver"; then
89 | supported_platforms+=" CentOS-Stream-$ver"
90 | fi
91 | done
92 | echo "supported_platforms=$supported_platforms" >> $GITHUB_OUTPUT
93 |
94 | testing-farm:
95 | name: ${{ matrix.platform }}/ansible-${{ matrix.ansible_version }}
96 | needs: prepare_vars
97 | strategy:
98 | fail-fast: false
99 | matrix:
100 | include:
101 | - platform: Fedora-41
102 | ansible_version: 2.17
103 | - platform: Fedora-42
104 | ansible_version: 2.19
105 | - platform: CentOS-7-latest
106 | ansible_version: 2.9
107 | - platform: CentOS-Stream-8
108 | ansible_version: 2.9
109 | # On CentOS-Stream-8, latest supported Ansible is 2.16
110 | - platform: CentOS-Stream-8
111 | ansible_version: 2.16
112 | - platform: CentOS-Stream-9
113 | ansible_version: 2.17
114 | - platform: CentOS-Stream-10
115 | ansible_version: 2.17
116 | runs-on: ubuntu-latest
117 | env:
118 | ARTIFACTS_DIR_NAME: "tf_${{ github.event.repository.name }}-${{ github.event.issue.number }}_\
119 | ${{ matrix.platform }}-${{ matrix.ansible_version }}_\
120 | ${{ needs.prepare_vars.outputs.datetime }}/artifacts"
121 | ARTIFACT_TARGET_DIR: /srv/pub/alt/${{ vars.SR_LSR_USER }}/logs
122 | steps:
123 | - name: Set variables with DATETIME and artifact location
124 | id: set_vars
125 | run: |
126 | printf -v DATETIME '%(%Y%m%d-%H%M%S)T' -1
127 | ARTIFACTS_DIR_NAME="tf_${{ github.event.repository.name }}-${{ github.event.issue.number }}_\
128 | ${{ matrix.platform }}-${{ matrix.ansible_version }}_$DATETIME/artifacts"
129 | ARTIFACTS_TARGET_DIR=/srv/pub/alt/${{ vars.SR_LSR_USER }}/logs
130 | ARTIFACTS_DIR=$ARTIFACTS_TARGET_DIR/$ARTIFACTS_DIR_NAME
131 | ARTIFACTS_URL=https://dl.fedoraproject.org/pub/alt/${{ vars.SR_LSR_USER }}/logs/$ARTIFACTS_DIR_NAME
132 | echo "DATETIME=$DATETIME" >> $GITHUB_OUTPUT
133 | echo "ARTIFACTS_DIR=$ARTIFACTS_DIR" >> $GITHUB_OUTPUT
134 | echo "ARTIFACTS_URL=$ARTIFACTS_URL" >> $GITHUB_OUTPUT
135 |
136 | - name: Set commit status as pending
137 | if: contains(needs.prepare_vars.outputs.supported_platforms, matrix.platform)
138 | uses: myrotvorets/set-commit-status-action@master
139 | with:
140 | sha: ${{ needs.prepare_vars.outputs.head_sha }}
141 | status: pending
142 | context: ${{ matrix.platform }}|ansible-${{ matrix.ansible_version }}
143 | description: Test started
144 | targetUrl: ""
145 |
146 | - name: Set commit status as success with a description that platform is skipped
147 | if: "!contains(needs.prepare_vars.outputs.supported_platforms, matrix.platform)"
148 | uses: myrotvorets/set-commit-status-action@master
149 | with:
150 | sha: ${{ needs.prepare_vars.outputs.head_sha }}
151 | status: success
152 | context: ${{ matrix.platform }}|ansible-${{ matrix.ansible_version }}
153 | description: The role does not support this platform. Skipping.
154 | targetUrl: ""
155 |
156 | - name: Run test in testing farm
157 | uses: sclorg/testing-farm-as-github-action@v4
158 | if: contains(needs.prepare_vars.outputs.supported_platforms, matrix.platform)
159 | with:
160 | git_ref: main
161 | pipeline_settings: '{ "type": "tmt-multihost" }'
162 | environment_settings: '{ "provisioning": { "tags": { "BusinessUnit": "system_roles" } } }'
163 | # Keeping SR_ARTIFACTS_URL at the bottom makes the link in logs clickable
164 | variables: "SR_ANSIBLE_VER=${{ matrix.ansible_version }};\
165 | SR_REPO_NAME=${{ github.event.repository.name }};\
166 | SR_GITHUB_ORG=${{ github.repository_owner }};\
167 | SR_PR_NUM=${{ github.event.issue.number }};\
168 | SR_ARTIFACTS_DIR=${{ steps.set_vars.outputs.ARTIFACTS_DIR }};\
169 | SR_TEST_LOCAL_CHANGES=false;\
170 | SR_LSR_USER=${{ vars.SR_LSR_USER }};\
171 | SR_ARTIFACTS_URL=${{ steps.set_vars.outputs.ARTIFACTS_URL }}"
172 | # Note that LINUXSYSTEMROLES_SSH_KEY must be single-line, TF doesn't read multi-line variables fine.
173 | secrets: "SR_LSR_DOMAIN=${{ secrets.SR_LSR_DOMAIN }};\
174 | SR_LSR_SSH_KEY=${{ secrets.SR_LSR_SSH_KEY }}"
175 | compose: ${{ matrix.platform }}
176 | # There are two blockers for using public ranch:
177 | # 1. multihost is not supported in public https://github.com/teemtee/tmt/issues/2620
178 | # 2. Security issue that leaks long secrets - Jira TFT-2698
179 | tf_scope: private
180 | api_key: ${{ secrets.TF_API_KEY_RH }}
181 | update_pull_request_status: false
182 | tmt_plan_filter: "tag:playbooks_parallel,timesync"
183 |
184 | - name: Set final commit status
185 | uses: myrotvorets/set-commit-status-action@master
186 | if: always() && contains(needs.prepare_vars.outputs.supported_platforms, matrix.platform)
187 | with:
188 | sha: ${{ needs.prepare_vars.outputs.head_sha }}
189 | status: ${{ job.status }}
190 | context: ${{ matrix.platform }}|ansible-${{ matrix.ansible_version }}
191 | description: Test finished
192 | targetUrl: ${{ steps.set_vars.outputs.ARTIFACTS_URL }}
193 |
--------------------------------------------------------------------------------
/.github/workflows/tft_citest_bad.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Re-run failed testing farm tests
3 | on:
4 | issue_comment:
5 | types:
6 | - created
7 | permissions:
8 | contents: read
9 | jobs:
10 | citest_bad_rerun:
11 | if: |
12 | github.event.issue.pull_request
13 | && contains(fromJson('["[citest_bad]", "[citest-bad]", "[citest bad]"]'), github.event.comment.body)
14 | && contains(fromJson('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)
15 | permissions:
16 | actions: write # for re-running failed jobs: https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#re-run-a-job-from-a-workflow-run
17 | runs-on: ubuntu-latest
18 | steps:
19 | - name: Wait 10s until tft.yml workflow is created and skipped because new comment don't match [citest]
20 | run: sleep 10s
21 |
22 | - name: Re-run failed jobs for this PR
23 | env:
24 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
25 | REPO: ${{ github.repository }}
26 | PR_TITLE: ${{ github.event.issue.title }}
27 | run: |
28 | PENDING_RUN=$(gh api "repos/$REPO/actions/workflows/tft.yml/runs?event=issue_comment" \
29 | | jq -r "[.workflow_runs[] | select( .display_title == \"$PR_TITLE\") | \
30 | select(.status == \"pending\" or .status == \"queued\" or .status == \"in_progress\") | .id][0]")
31 | # if pending run don't exist, take the last run with failure state
32 | if [ "$PENDING_RUN" != "null" ]; then
33 | echo "The workflow $PENDING_RUN is still running, wait for it to finish to re-run"
34 | exit 1
35 | fi
36 | RUN_ID=$(gh api "repos/$REPO/actions/workflows/tft.yml/runs?event=issue_comment" \
37 | | jq -r "[.workflow_runs[] | select( .display_title == \"$PR_TITLE\" ) | select( .conclusion == \"failure\" ) | .id][0]")
38 | if [ "$RUN_ID" = "null" ]; then
39 | echo "Failed workflow not found, exiting"
40 | exit 1
41 | fi
42 | echo "Re-running workflow $RUN_ID"
43 | gh api --method POST repos/$REPO/actions/runs/$RUN_ID/rerun-failed-jobs
44 |
--------------------------------------------------------------------------------
/.github/workflows/weekly_ci.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # yamllint disable rule:line-length
3 | name: Weekly CI trigger
4 | on: # yamllint disable-line rule:truthy
5 | workflow_dispatch:
6 | schedule:
7 | - cron: 0 2 * * 0
8 | env:
9 | BRANCH_NAME: weekly-ci
10 | COMMIT_MESSAGE: "ci: This PR is to trigger periodic CI testing"
11 | BODY_MESSAGE: >-
12 | This PR is for the purpose of triggering periodic CI testing.
13 | We don't currently have a way to trigger CI without a PR,
14 | so this PR serves that purpose.
15 | COMMENT: "[citest]"
16 | permissions:
17 | contents: read
18 | jobs:
19 | weekly_ci:
20 | runs-on: ubuntu-latest
21 | permissions:
22 | issues: write
23 | pull-requests: write
24 | contents: write
25 | steps:
26 | - name: Update pip, git
27 | run: |
28 | set -euxo pipefail
29 | sudo apt update
30 | sudo apt install -y git
31 |
32 | - name: Checkout latest code
33 | uses: actions/checkout@v4
34 | with:
35 | fetch-depth: 0
36 | - name: Create or rebase commit, add dump_packages callback
37 | run: |
38 | set -euxo pipefail
39 |
40 | git config --global user.name "github-actions[bot]"
41 | git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
42 | git checkout ${{ env.BRANCH_NAME }} || git checkout -b ${{ env.BRANCH_NAME }}
43 | git rebase main
44 | if [ ! -d tests/callback_plugins ]; then
45 | mkdir -p tests/callback_plugins
46 | fi
47 | curl -L -s -o tests/callback_plugins/dump_packages.py https://raw.githubusercontent.com/linux-system-roles/auto-maintenance/main/callback_plugins/dump_packages.py
48 | git add tests/callback_plugins
49 | git commit --allow-empty -m "${{ env.COMMIT_MESSAGE }}"
50 | git push -f --set-upstream origin ${{ env.BRANCH_NAME }}
51 |
52 | - name: Create and comment pull request
53 | uses: actions/github-script@v7
54 | with:
55 | github-token: ${{ secrets.GH_PUSH_TOKEN }}
56 | script: |
57 | const head = [context.repo.owner, ":", "${{ env.BRANCH_NAME }}"].join("");
58 | const response = await github.rest.pulls.list({
59 | owner: context.repo.owner,
60 | repo: context.repo.repo,
61 | head: head,
62 | base: context.ref,
63 | state: "open"
64 | });
65 | let pr_number = '';
66 | if (response.data.length === 0) {
67 | pr_number = (await github.rest.pulls.create({
68 | owner: context.repo.owner,
69 | repo: context.repo.repo,
70 | title: "${{ env.COMMIT_MESSAGE }}",
71 | body: "${{ env.BODY_MESSAGE }}",
72 | head: "${{ env.BRANCH_NAME }}",
73 | base: context.ref,
74 | draft: true
75 | })).data.number;
76 | } else {
77 | pr_number = response.data[0].number;
78 | }
79 | github.rest.issues.createComment({
80 | owner: context.repo.owner,
81 | repo: context.repo.repo,
82 | issue_number: pr_number,
83 | body: "${{ env.COMMENT }}",
84 | });
85 |
--------------------------------------------------------------------------------
/.github/workflows/woke.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # yamllint disable rule:line-length
3 | name: Woke
4 | on: # yamllint disable-line rule:truthy
5 | - pull_request
6 | jobs:
7 | woke:
8 | name: Detect non-inclusive language
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Checkout
12 | uses: actions/checkout@v4
13 |
14 | - name: Run lsr-woke-action
15 | # Originally, uses: get-woke/woke-action@v0
16 | uses: linux-system-roles/lsr-woke-action@main
17 | with:
18 | woke-args: "-c https://raw.githubusercontent.com/linux-system-roles/tox-lsr/main/src/tox_lsr/config_files/woke.yml --count-only-error-for-failure"
19 | # Cause the check to fail on any broke rules
20 | fail-on-error: true
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | passes.yml
2 | vault.yml
3 | *.pyc
4 | *.retry
5 | /tests/.coverage
6 | /tests/htmlcov*
7 | /.tox
8 | /venv*/
9 | /.venv/
10 | .vscode/
11 | artifacts/
12 | __pycache__/
13 | *~
14 | .pytest_cache/
15 |
--------------------------------------------------------------------------------
/.markdownlint.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # Default state for all rules
3 | default: true
4 |
5 | # Path to configuration file to extend
6 | extends: null
7 |
8 | # MD001/heading-increment/header-increment - Heading levels should only increment by one level at a time
9 | MD001: true
10 |
11 | # MD002/first-heading-h1/first-header-h1 - First heading should be a top-level heading
12 | MD002:
13 | # Heading level
14 | level: 1
15 |
16 | # MD003/heading-style/header-style - Heading style
17 | MD003:
18 | # Heading style
19 | style: "consistent"
20 |
21 | # MD004/ul-style - Unordered list style
22 | MD004:
23 | # List style
24 | style: "consistent"
25 |
26 | # MD005/list-indent - Inconsistent indentation for list items at the same level
27 | MD005: true
28 |
29 | # MD006/ul-start-left - Consider starting bulleted lists at the beginning of the line
30 | MD006: true
31 |
32 | # MD007/ul-indent - Unordered list indentation
33 | MD007:
34 | # Spaces for indent
35 | indent: 2
36 | # Whether to indent the first level of the list
37 | start_indented: false
38 | # Spaces for first level indent (when start_indented is set)
39 | start_indent: 2
40 |
41 | # MD009/no-trailing-spaces - Trailing spaces
42 | MD009:
43 | # Spaces for line break
44 | br_spaces: 2
45 | # Allow spaces for empty lines in list items
46 | list_item_empty_lines: false
47 | # Include unnecessary breaks
48 | strict: false
49 |
50 | # MD010/no-hard-tabs - Hard tabs
51 | MD010:
52 | # Include code blocks
53 | code_blocks: true
54 | # Fenced code languages to ignore
55 | ignore_code_languages: []
56 | # Number of spaces for each hard tab
57 | spaces_per_tab: 1
58 |
59 | # MD011/no-reversed-links - Reversed link syntax
60 | MD011: true
61 |
62 | # MD012/no-multiple-blanks - Multiple consecutive blank lines
63 | MD012:
64 | # Consecutive blank lines
65 | maximum: 1
66 |
67 | # Modified for LSR
68 | # GFM does not limit line length
69 | # MD013/line-length - Line length
70 | MD013: false
71 | # # Number of characters
72 | # # line_length: 80
73 | # line_length: 999
74 | # # Number of characters for headings
75 | # heading_line_length: 80
76 | # # Number of characters for code blocks
77 | # code_block_line_length: 80
78 | # # Include code blocks
79 | # code_blocks: true
80 | # # Include tables
81 | # tables: true
82 | # # Include headings
83 | # headings: true
84 | # # Include headings
85 | # headers: true
86 | # # Strict length checking
87 | # strict: false
88 | # # Stern length checking
89 | # stern: false
90 |
91 | # MD014/commands-show-output - Dollar signs used before commands without showing output
92 | MD014: true
93 |
94 | # MD018/no-missing-space-atx - No space after hash on atx style heading
95 | MD018: true
96 |
97 | # MD019/no-multiple-space-atx - Multiple spaces after hash on atx style heading
98 | MD019: true
99 |
100 | # MD020/no-missing-space-closed-atx - No space inside hashes on closed atx style heading
101 | MD020: true
102 |
103 | # MD021/no-multiple-space-closed-atx - Multiple spaces inside hashes on closed atx style heading
104 | MD021: true
105 |
106 | # MD022/blanks-around-headings/blanks-around-headers - Headings should be surrounded by blank lines
107 | MD022:
108 | # Blank lines above heading
109 | lines_above: 1
110 | # Blank lines below heading
111 | lines_below: 1
112 |
113 | # MD023/heading-start-left/header-start-left - Headings must start at the beginning of the line
114 | MD023: true
115 |
116 | # MD024/no-duplicate-heading/no-duplicate-header - Multiple headings with the same content
117 | MD024: true
118 |
119 | # MD025/single-title/single-h1 - Multiple top-level headings in the same document
120 | MD025:
121 | # Heading level
122 | level: 1
123 | # RegExp for matching title in front matter
124 | front_matter_title: "^\\s*title\\s*[:=]"
125 |
126 | # MD026/no-trailing-punctuation - Trailing punctuation in heading
127 | MD026:
128 | # Punctuation characters not allowed at end of headings
129 | punctuation: ".,;:!。,;:!"
130 |
131 | # MD027/no-multiple-space-blockquote - Multiple spaces after blockquote symbol
132 | MD027: true
133 |
134 | # MD028/no-blanks-blockquote - Blank line inside blockquote
135 | MD028: true
136 |
137 | # MD029/ol-prefix - Ordered list item prefix
138 | MD029:
139 | # List style
140 | style: "one_or_ordered"
141 |
142 | # MD030/list-marker-space - Spaces after list markers
143 | MD030:
144 | # Spaces for single-line unordered list items
145 | ul_single: 1
146 | # Spaces for single-line ordered list items
147 | ol_single: 1
148 | # Spaces for multi-line unordered list items
149 | ul_multi: 1
150 | # Spaces for multi-line ordered list items
151 | ol_multi: 1
152 |
153 | # MD031/blanks-around-fences - Fenced code blocks should be surrounded by blank lines
154 | MD031:
155 | # Include list items
156 | list_items: true
157 |
158 | # MD032/blanks-around-lists - Lists should be surrounded by blank lines
159 | MD032: true
160 |
161 | # MD033/no-inline-html - Inline HTML
162 | MD033:
163 | # Allowed elements
164 | allowed_elements: []
165 |
166 | # MD034/no-bare-urls - Bare URL used
167 | MD034: true
168 |
169 | # MD035/hr-style - Horizontal rule style
170 | MD035:
171 | # Horizontal rule style
172 | style: "consistent"
173 |
174 | # MD036/no-emphasis-as-heading/no-emphasis-as-header - Emphasis used instead of a heading
175 | MD036:
176 | # Punctuation characters
177 | punctuation: ".,;:!?。,;:!?"
178 |
179 | # MD037/no-space-in-emphasis - Spaces inside emphasis markers
180 | MD037: true
181 |
182 | # MD038/no-space-in-code - Spaces inside code span elements
183 | MD038: true
184 |
185 | # MD039/no-space-in-links - Spaces inside link text
186 | MD039: true
187 |
188 | # MD040/fenced-code-language - Fenced code blocks should have a language specified
189 | MD040:
190 | # List of languages
191 | allowed_languages: []
192 | # Require language only
193 | language_only: false
194 |
195 | # MD041/first-line-heading/first-line-h1 - First line in a file should be a top-level heading
196 | MD041:
197 | # Heading level
198 | level: 1
199 | # RegExp for matching title in front matter
200 | front_matter_title: "^\\s*title\\s*[:=]"
201 |
202 | # MD042/no-empty-links - No empty links
203 | MD042: true
204 |
205 | # Modified for LSR
206 | # Disabling, we do not need this
207 | # MD043/required-headings/required-headers - Required heading structure
208 | MD043: false
209 | # # List of headings
210 | # headings: []
211 | # # List of headings
212 | # headers: []
213 | # # Match case of headings
214 | # match_case: false
215 |
216 | # MD044/proper-names - Proper names should have the correct capitalization
217 | MD044:
218 | # List of proper names
219 | names: []
220 | # Include code blocks
221 | code_blocks: true
222 | # Include HTML elements
223 | html_elements: true
224 |
225 | # MD045/no-alt-text - Images should have alternate text (alt text)
226 | MD045: true
227 |
228 | # MD046/code-block-style - Code block style
229 | MD046:
230 | # Block style
231 | style: "consistent"
232 |
233 | # MD047/single-trailing-newline - Files should end with a single newline character
234 | MD047: true
235 |
236 | # MD048/code-fence-style - Code fence style
237 | MD048:
238 | # Code fence style
239 | style: "consistent"
240 |
241 | # MD049/emphasis-style - Emphasis style should be consistent
242 | MD049:
243 | # Emphasis style should be consistent
244 | style: "consistent"
245 |
246 | # MD050/strong-style - Strong style should be consistent
247 | MD050:
248 | # Strong style should be consistent
249 | style: "consistent"
250 |
251 | # MD051/link-fragments - Link fragments should be valid
252 | MD051: true
253 |
254 | # MD052/reference-links-images - Reference links and images should use a label that is defined
255 | MD052: true
256 |
257 | # MD053/link-image-reference-definitions - Link and image reference definitions should be needed
258 | MD053:
259 | # Ignored definitions
260 | ignored_definitions:
261 | - "//"
262 |
--------------------------------------------------------------------------------
/.ostree/README.md:
--------------------------------------------------------------------------------
1 | *NOTE*: The `*.txt` files are used by `get_ostree_data.sh` to create the lists
2 | of packages, and to find other system roles used by this role. DO NOT use them
3 | directly.
4 |
--------------------------------------------------------------------------------
/.ostree/get_ostree_data.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -euo pipefail
4 |
5 | ostree_dir="${OSTREE_DIR:-"$(dirname "$(realpath "$0")")"}"
6 |
7 | if [ -z "${4:-}" ] || [ "${1:-}" = help ] || [ "${1:-}" = -h ]; then
8 | cat <&2 echo ERROR - could not find role "$role" - please use ANSIBLE_COLLECTIONS_PATH
64 | exit 2
65 | }
66 |
67 | get_packages() {
68 | local ostree_dir pkgtype pkgfile rolefile
69 | ostree_dir="$1"
70 | for pkgtype in "${pkgtypes[@]}"; do
71 | for suff in "" "-$distro" "-${distro}-${major_ver}" "-${distro}-${ver}"; do
72 | pkgfile="$ostree_dir/packages-${pkgtype}${suff}.txt"
73 | if [ -f "$pkgfile" ]; then
74 | cat "$pkgfile"
75 | fi
76 | done
77 | rolefile="$ostree_dir/roles-${pkgtype}.txt"
78 | if [ -f "$rolefile" ]; then
79 | local roles role rolepath
80 | roles="$(cat "$rolefile")"
81 | for role in $roles; do
82 | rolepath="$(get_rolepath "$ostree_dir" "$role")"
83 | if [ -z "$rolepath" ]; then
84 | 1>&2 echo ERROR - could not find role "$role" - please use ANSIBLE_COLLECTIONS_PATH
85 | exit 2
86 | fi
87 | get_packages "$rolepath"
88 | done
89 | fi
90 | done | sort -u
91 | }
92 |
93 | format_packages_json() {
94 | local comma pkgs pkg
95 | comma=""
96 | pkgs="["
97 | while read -r pkg; do
98 | pkgs="${pkgs}${comma}\"${pkg}\""
99 | comma=,
100 | done
101 | pkgs="${pkgs}]"
102 | echo "$pkgs"
103 | }
104 |
105 | format_packages_raw() {
106 | cat
107 | }
108 |
109 | format_packages_yaml() {
110 | while read -r pkg; do
111 | echo "- $pkg"
112 | done
113 | }
114 |
115 | format_packages_toml() {
116 | while read -r pkg; do
117 | echo "[[packages]]"
118 | echo "name = \"$pkg\""
119 | echo "version = \"*\""
120 | done
121 | }
122 |
123 | distro="${distro_ver%%-*}"
124 | ver="${distro_ver##*-}"
125 | if [[ "$ver" =~ ^([0-9]*) ]]; then
126 | major_ver="${BASH_REMATCH[1]}"
127 | else
128 | echo ERROR: cannot parse major version number from version "$ver"
129 | exit 1
130 | fi
131 |
132 | "get_$category" "$ostree_dir" | "format_${category}_$format"
133 |
--------------------------------------------------------------------------------
/.ostree/packages-runtime-CentOS-7.txt:
--------------------------------------------------------------------------------
1 | ntp
2 |
--------------------------------------------------------------------------------
/.ostree/packages-runtime-RedHat-6.txt:
--------------------------------------------------------------------------------
1 | ntp
2 |
--------------------------------------------------------------------------------
/.ostree/packages-runtime-RedHat-7.txt:
--------------------------------------------------------------------------------
1 | ntp
2 |
--------------------------------------------------------------------------------
/.ostree/packages-runtime.txt:
--------------------------------------------------------------------------------
1 | chrony
2 | linuxptp
3 |
--------------------------------------------------------------------------------
/.ostree/packages-testing-CentOS-7.txt:
--------------------------------------------------------------------------------
1 | ntp
2 |
--------------------------------------------------------------------------------
/.ostree/packages-testing-RedHat-6.txt:
--------------------------------------------------------------------------------
1 | ntp
2 |
--------------------------------------------------------------------------------
/.ostree/packages-testing-RedHat-7.txt:
--------------------------------------------------------------------------------
1 | ntp
2 |
--------------------------------------------------------------------------------
/.ostree/packages-testing.txt:
--------------------------------------------------------------------------------
1 | chrony
2 | ethtool
3 | iproute
4 |
--------------------------------------------------------------------------------
/.pandoc_template.html5:
--------------------------------------------------------------------------------
1 | $--| GitHub HTML5 Pandoc Template" v2.2 | 2020/08/12 | pandoc v2.1.1
2 |
3 |
51 | $-------------------------------------------------------------------------> lang
52 |
53 |
54 | $--=============================================================================
55 | $-- METADATA
56 | $--=============================================================================
57 |
58 |
59 |
60 | $-----------------------------------------------------------------------> author
61 | $for(author-meta)$
62 |
63 | $endfor$
64 | $-------------------------------------------------------------------------> date
65 | $if(date-meta)$
66 |
67 | $endif$
68 | $---------------------------------------------------------------------> keywords
69 | $if(keywords)$
70 |
71 | $endif$
72 | $------------------------------------------------------------------> description
73 | $if(description)$
74 |
75 | $endif$
76 | $------------------------------------------------------------------------> title
77 | $if(title-prefix)$$title-prefix$ – $endif$$pagetitle$
78 | $--===========================================================================
79 | $-- CSS STYLESHEETS
80 | $--===========================================================================
81 | $-- Here comes the placeholder (within double braces) that will be replaced
82 | $-- by the CSS file in the finalized template:
83 |
86 | $-------------------------------------------------------------------------------
87 |
88 | $-------------------------------------------------------------------------------
89 | $if(quotes)$
90 |
91 | $endif$
92 | $-------------------------------------------------------------> highlighting-css
93 | $if(highlighting-css)$
94 |
97 | $endif$
98 | $--------------------------------------------------------------------------> css
99 | $for(css)$
100 |
101 | $endfor$
102 | $-------------------------------------------------------------------------> math
103 | $if(math)$
104 | $math$
105 | $endif$
106 | $-------------------------------------------------------------------------------
107 |
110 | $--------------------------------------------------------------> header-includes
111 | $for(header-includes)$
112 | $header-includes$
113 | $endfor$
114 | $-------------------------------------------------------------------------------
115 |
116 |
117 |
118 | $---------------------------------------------------------------> include-before
119 | $for(include-before)$
120 | $include-before$
121 | $endfor$
122 | $-->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> IF: title
123 | $if(title)$
124 |
125 | $title$
126 | $---------------------------------------------------------------------> subtitle
127 | $if(subtitle)$
128 | $subtitle$
129 | $endif$
130 | $-----------------------------------------------------------------------> author
131 | $for(author)$
132 | $author$
133 | $endfor$
134 | $-------------------------------------------------------------------------> date
135 | $if(date)$
136 | $date$
137 | $endif$
138 | $----------------------------------------------------------------------> summary
139 | $if(summary)$
140 |
141 | $summary$
142 |
143 | $endif$
144 | $-------------------------------------------------------------------------------
145 |
146 | $endif$
147 | $--<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< END IF: title
148 | $--------------------------------------------------------------------------> toc
149 | $if(toc)$
150 |
151 |
155 |
156 | $endif$
157 | $-------------------------------------------------------------------------> body
158 | $body$
159 | $----------------------------------------------------------------> include-after
160 | $for(include-after)$
161 | $include-after$
162 | $endfor$
163 | $-------------------------------------------------------------------------------
164 |
165 |
166 |
167 |
--------------------------------------------------------------------------------
/.sanity-ansible-ignore-2.10.txt:
--------------------------------------------------------------------------------
1 | plugins/modules/timesync_provider.sh shebang
2 | plugins/modules/timesync_provider.yml validate-modules:missing-gplv3-license
3 |
--------------------------------------------------------------------------------
/.sanity-ansible-ignore-2.11.txt:
--------------------------------------------------------------------------------
1 | plugins/modules/timesync_provider.sh shebang
2 | plugins/modules/timesync_provider.yml validate-modules:missing-gplv3-license
3 |
--------------------------------------------------------------------------------
/.sanity-ansible-ignore-2.12.txt:
--------------------------------------------------------------------------------
1 | plugins/modules/timesync_provider.sh shebang
2 | plugins/modules/timesync_provider.yml validate-modules:missing-gplv3-license
3 |
--------------------------------------------------------------------------------
/.sanity-ansible-ignore-2.13.txt:
--------------------------------------------------------------------------------
1 | plugins/modules/timesync_provider.sh shebang
2 | plugins/modules/timesync_provider.yml validate-modules:missing-gplv3-license
3 |
--------------------------------------------------------------------------------
/.sanity-ansible-ignore-2.14.txt:
--------------------------------------------------------------------------------
1 | plugins/modules/timesync_provider.sh shebang
2 | plugins/modules/timesync_provider.yml validate-modules:missing-gplv3-license
3 | plugins/modules/timesync_provider.sh validate-modules:invalid-extension
4 | plugins/modules/timesync_provider.sh validate-modules:python-syntax-error
5 |
--------------------------------------------------------------------------------
/.sanity-ansible-ignore-2.15.txt:
--------------------------------------------------------------------------------
1 | plugins/modules/timesync_provider.sh shebang
2 | plugins/modules/timesync_provider.yml validate-modules:missing-gplv3-license
3 | plugins/modules/timesync_provider.sh validate-modules:invalid-extension
4 | plugins/modules/timesync_provider.sh validate-modules:python-syntax-error
5 |
--------------------------------------------------------------------------------
/.sanity-ansible-ignore-2.16.txt:
--------------------------------------------------------------------------------
1 | plugins/modules/timesync_provider.sh shebang
2 | plugins/modules/timesync_provider.yml validate-modules:missing-gplv3-license
3 | plugins/modules/timesync_provider.sh validate-modules:invalid-extension
4 | plugins/modules/timesync_provider.sh validate-modules:python-syntax-error
5 |
--------------------------------------------------------------------------------
/.sanity-ansible-ignore-2.17.txt:
--------------------------------------------------------------------------------
1 | plugins/modules/timesync_provider.sh shebang
2 | plugins/modules/timesync_provider.yml validate-modules:missing-gplv3-license
3 | plugins/modules/timesync_provider.sh validate-modules:invalid-extension
4 | plugins/modules/timesync_provider.sh validate-modules:missing-gplv3-license
5 |
--------------------------------------------------------------------------------
/.sanity-ansible-ignore-2.9.txt:
--------------------------------------------------------------------------------
1 | plugins/modules/timesync_provider.sh shebang
2 | plugins/modules/timesync_provider.yml validate-modules:missing-gplv3-license
3 |
--------------------------------------------------------------------------------
/.yamllint.yml:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: MIT
2 | ---
3 | ignore: |
4 | /.tox/
5 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | Changelog
2 | =========
3 |
4 | [1.10.2] - 2025-07-09
5 | --------------------
6 |
7 | ### Other Changes
8 |
9 | - ci: bump sclorg/testing-farm-as-github-action from 3 to 4 (#290)
10 | - ci: bump tox-lsr to 3.8.0; rename qemu/kvm tests (#291)
11 | - ci: Add Fedora 42; use tox-lsr 3.9.0; use lsr-report-errors for qemu tests (#292)
12 | - ci: Add support for bootc end-to-end validation tests (#293)
13 | - ci: Use ansible 2.19 for fedora 42 testing; support python 3.13 (#294)
14 | - refactor: support ansible 2.19; fix ansible-lint issues (#295)
15 |
16 | [1.10.1] - 2025-04-28
17 | --------------------
18 |
19 | ### Other Changes
20 |
21 | - test: add test for secccomp on el9/el10 (#288)
22 |
23 | [1.10.0] - 2025-04-23
24 | --------------------
25 |
26 | ### New Features
27 |
28 | - feat: add support for timesync_ntp_ip_family (#277)
29 |
30 | ### Bug Fixes
31 |
32 | - fix: add default seccomp filters for el9/10 (#279)
33 |
34 | ### Other Changes
35 |
36 | - ci: Check spelling with codespell (#267)
37 | - ci: ansible-plugin-scan is disabled for now (#268)
38 | - ci: bump ansible-lint to v25; provide collection requirements for ansible-lint (#271)
39 | - ci: Add test plan that runs CI tests and customize it for each role (#273)
40 | - ci: In test plans, prefix all relate variables with SR_ (#274)
41 | - ci: Create inventory for wrapper test with inventory_hostname (#275)
42 | - ci: Fix bug with ARTIFACTS_URL after prefixing with SR_ (#276)
43 | - ci: several changes related to new qemu test, ansible-lint, python versions, ubuntu versions (#281)
44 | - refactor: make OracleLinux vars files symlinks to RedHat vars files (#283)
45 | - ci: use tox-lsr 3.6.0; improve qemu test logging (#284)
46 | - ci: skip storage scsi, nvme tests in github qemu ci (#285)
47 | - test: ensure tests cleanup and restore the system state (#286)
48 |
49 | [1.9.2] - 2025-01-09
50 | --------------------
51 |
52 | ### Other Changes
53 |
54 | - ci: Use Fedora 41, drop Fedora 39 (#264)
55 | - ci: Use Fedora 41, drop Fedora 39 - part two (#265)
56 |
57 | [1.9.1] - 2024-10-30
58 | --------------------
59 |
60 | ### Other Changes
61 |
62 | - ci: Add tags to TF workflow, allow more [citest bad] formats (#258)
63 | - ci: ansible-test action now requires ansible-core version (#259)
64 | - ci: add YAML header to github action workflow files (#260)
65 | - refactor: Use vars/RedHat_N.yml symlink for CentOS, Rocky, Alma wherever possible (#262)
66 |
67 | [1.9.0] - 2024-08-16
68 | --------------------
69 |
70 | ### New Features
71 |
72 | - feat: Handle reboot for transactional update systems (#256)
73 |
74 | ### Other Changes
75 |
76 | - ci: Add workflow for ci_test bad, use remote fmf plan (#254)
77 | - ci: Fix missing slash in ARTIFACTS_URL (#255)
78 |
79 | [1.8.6] - 2024-08-01
80 | --------------------
81 |
82 | ### Other Changes
83 |
84 | - ci: Add tft plan and workflow (#248)
85 | - docs: add module documentation for timesync_provider (#250)
86 | - ci: Update fmf plan to add a separate job to prepare managed nodes (#251)
87 | - ci: Bump sclorg/testing-farm-as-github-action from 2 to 3 (#252)
88 |
89 | [1.8.5] - 2024-07-02
90 | --------------------
91 |
92 | ### Bug Fixes
93 |
94 | - fix: add support for EL10 (#245)
95 | - fix: Don't use chrony-dhcp sourcedir on EL8 systems (#246)
96 |
97 | ### Other Changes
98 |
99 | - ci: ansible-lint action now requires absolute directory (#244)
100 |
101 | [1.8.4] - 2024-06-11
102 | --------------------
103 |
104 | ### Other Changes
105 |
106 | - ci: use tox-lsr 3.3.0 which uses ansible-test 2.17 (#239)
107 | - ci: tox-lsr 3.4.0 - fix py27 tests; move other checks to py310 (#241)
108 | - ci: Add supported_ansible_also to .ansible-lint (#242)
109 |
110 | [1.8.3] - 2024-04-04
111 | --------------------
112 |
113 | ### Other Changes
114 |
115 | - ci: fix python unit test - copy pytest config to tests/unit (#234)
116 | - ci: Bump ansible/ansible-lint from 6 to 24 (#235)
117 | - ci: Bump mathieudutour/github-tag-action from 6.1 to 6.2 (#237)
118 |
119 | [1.8.2] - 2024-01-16
120 | --------------------
121 |
122 | ### Other Changes
123 |
124 | - ci: support ansible-lint and ansible-test 2.16 (#231)
125 | - ci: Use supported ansible-lint action; run ansible-lint against the collection (#232)
126 |
127 | [1.8.1] - 2023-12-08
128 | --------------------
129 |
130 | ### Other Changes
131 |
132 | - ci: bump actions/github-script from 6 to 7 (#227)
133 | - refactor: get_ostree_data.sh use env shebang - remove from .sanity* (#228)
134 |
135 | [1.8.0] - 2023-11-29
136 | --------------------
137 |
138 | ### New Features
139 |
140 | - feat: support for ostree systems (#224)
141 |
142 | [1.7.9] - 2023-11-06
143 | --------------------
144 |
145 | ### Other Changes
146 |
147 | - ci: Fix implicit octal values in main.yml (#220)
148 | - ci: Add ALP-Dolomite var file (#221)
149 |
150 | [1.7.8] - 2023-10-23
151 | --------------------
152 |
153 | ### Other Changes
154 |
155 | - Bump actions/checkout from 3 to 4 (#209)
156 | - ci: ensure dependabot git commit message conforms to commitlint (#212)
157 | - ci: use dump_packages.py callback to get packages used by role (#214)
158 | - refactor: Add CentOS 7-8, RedHat 7-8 and AlmaLinux 8-9 var files (#216)
159 | - ci: tox-lsr version 3.1.1 (#218)
160 |
161 | [1.7.7] - 2023-09-11
162 | --------------------
163 |
164 | ### Other Changes
165 |
166 | - ci: Add markdownlint, test_converting_readme, and build_docs workflows (#205)
167 |
168 | - markdownlint runs against README.md to avoid any issues with
169 | converting it to HTML
170 | - test_converting_readme converts README.md > HTML and uploads this test
171 | artifact to ensure that conversion works fine
172 | - build_docs converts README.md > HTML and pushes the result to the
173 | docs branch to publish dosc to GitHub pages site.
174 | - Fix markdown issues in README.md
175 |
176 | Signed-off-by: Sergei Petrosian
177 |
178 | - docs: Make badges consistent, run markdownlint on all .md files (#206)
179 |
180 | - Consistently generate badges for GH workflows in README RHELPLAN-146921
181 | - Run markdownlint on all .md files
182 | - Add custom-woke-action if not used already
183 | - Rename woke action to Woke for a pretty badge
184 |
185 | Signed-off-by: Sergei Petrosian
186 |
187 | - ci: Remove badges from README.md prior to converting to HTML (#207)
188 |
189 | - Remove thematic break after badges
190 | - Remove badges from README.md prior to converting to HTML
191 |
192 | Signed-off-by: Sergei Petrosian
193 |
194 | [1.7.7] - 2023-09-11
195 | --------------------
196 |
197 | ### Other Changes
198 |
199 | - ci: Add markdownlint, test_converting_readme, and build_docs workflows (#205)
200 |
201 | - markdownlint runs against README.md to avoid any issues with
202 | converting it to HTML
203 | - test_converting_readme converts README.md > HTML and uploads this test
204 | artifact to ensure that conversion works fine
205 | - build_docs converts README.md > HTML and pushes the result to the
206 | docs branch to publish dosc to GitHub pages site.
207 | - Fix markdown issues in README.md
208 |
209 | Signed-off-by: Sergei Petrosian
210 |
211 | - docs: Make badges consistent, run markdownlint on all .md files (#206)
212 |
213 | - Consistently generate badges for GH workflows in README RHELPLAN-146921
214 | - Run markdownlint on all .md files
215 | - Add custom-woke-action if not used already
216 | - Rename woke action to Woke for a pretty badge
217 |
218 | Signed-off-by: Sergei Petrosian
219 |
220 | - ci: Remove badges from README.md prior to converting to HTML (#207)
221 |
222 | - Remove thematic break after badges
223 | - Remove badges from README.md prior to converting to HTML
224 |
225 | Signed-off-by: Sergei Petrosian
226 |
227 | [1.7.6] - 2023-07-19
228 | --------------------
229 |
230 | ### Bug Fixes
231 |
232 | - fix: facts being gathered unnecessarily (#202)
233 |
234 | ### Other Changes
235 |
236 | - docs: Consistent contributing.md for all roles - allow role specific contributing.md section (#196)
237 | - ci: update tox-lsr to version 3.0.0 (#197)
238 | - ci: Add pull request template and run commitlint on PR title only (#198)
239 | - ci: Rename commitlint to PR title Lint, echo PR titles from env var (#199)
240 | - ci: ansible-lint - ignore var-naming[no-role-prefix] (#200)
241 | - ci: ansible-test ignores file for ansible-core 2.15 (#201)
242 |
243 | [1.7.5] - 2023-04-27
244 | --------------------
245 |
246 | ### Other Changes
247 |
248 | - test: check generated files for ansible_managed, fingerprint
249 | - ci: Add commitlint GitHub action to ensure conventional commits with feedback
250 |
251 | [1.7.4] - 2023-04-13
252 | --------------------
253 |
254 | ### Other Changes
255 |
256 | - use pipefail if shell uses pipes (#189)
257 |
258 | [1.7.3] - 2023-04-06
259 | --------------------
260 |
261 | ### Bug Fixes
262 |
263 | - Update chrony.conf location for Debian (#187)
264 |
265 | ### Other Changes
266 |
267 | - suppress shellcheck issue (#176)
268 | - Fix jinja formatting issue (#178)
269 | - Add README-ansible.md to refer Ansible intro page on linux-system-roles.github.io (#185)
270 | - Fingerprint RHEL System Role managed config files (#186)
271 |
272 | [1.7.2] - 2023-01-20
273 | --------------------
274 |
275 | ### New Features
276 |
277 | - none
278 |
279 | ### Bug Fixes
280 |
281 | - fixes for ansible-lint 6.x
282 |
283 | ### Other Changes
284 |
285 | - ensure ethtool is installed where needed
286 | - Add check for non-inclusive language; (#170)
287 | - Clean up / Workaround non-inclusive words
288 | - update ignore files for ansible-test 2.14 (#172)
289 |
290 | [1.7.1] - 2022-11-01
291 | --------------------
292 |
293 | ### New Features
294 |
295 | - none
296 |
297 | ### Bug Fixes
298 |
299 | - none
300 |
301 | ### Other Changes
302 |
303 | - Update timestamping checks using ethtool
304 |
305 | New ethtool versions don't print the upper-case timestamping constants
306 | anymore. Match the lower-case strings instead.
307 |
308 | [1.7.0] - 2022-09-19
309 | --------------------
310 |
311 | ### New Features
312 |
313 | - adding support for Oracle Linux 6,7,8 and 9
314 |
315 | ### Bug Fixes
316 |
317 | - Update chrony.conf.j2
318 |
319 | Variables are defined as string in Jinja2 template and the operators
320 | on line 26 gives '<' not supported between instances of 'str' and 'float
321 | on line 43 gives '>' not supported between instances of 'str' and 'float
322 |
323 | - Updated: type casting in overall timesync templates for testing
324 |
325 | - Updated: type casting adjusted (timesync_max_distance <= int)
326 |
327 | ### Other Changes
328 |
329 | - use ansible_playbook_filepath for ansible-playbook command
330 |
331 | [1.6.9] - 2022-07-19
332 | --------------------
333 |
334 | ### New Features
335 |
336 | - none
337 |
338 | ### Bug Fixes
339 |
340 | - none
341 |
342 | ### Other Changes
343 |
344 | - make all tests work with gather_facts: false
345 |
346 | Ensure all tests work when using ANSIBLE_GATHERING=explicit
347 |
348 | - make min_ansible_version a string in meta/main.yml
349 |
350 | The Ansible developers say that `min_ansible_version` in meta/main.yml
351 | must be a `string` value like `"2.9"`, not a `float` value like `2.9`.
352 |
353 | - Add CHANGELOG.md
354 |
355 | [1.6.8] - 2022-05-06
356 | --------------------
357 |
358 | ### New Features
359 |
360 | - none
361 |
362 | ### Bug Fixes
363 |
364 | - none
365 |
366 | ### Other Changes
367 |
368 | - bump tox-lsr version to 2.11.0; remove py37; add py310
369 |
370 | [1.6.7] - 2022-04-14
371 | --------------------
372 |
373 | ### New Features
374 |
375 | - support gather\_facts: false; support setup-snapshot.yml
376 |
377 | ### Bug Fixes
378 |
379 | - none
380 |
381 | ### Other Changes
382 |
383 | - none
384 |
385 | [1.6.6] - 2022-02-28
386 | --------------------
387 |
388 | ### New Features
389 |
390 | - none
391 |
392 | ### Bug Fixes
393 |
394 | - handle errors with stopping services
395 |
396 | ### Other Changes
397 |
398 | - bump tox-lsr version to 2.10.1
399 |
400 | [1.6.5] - 2022-01-12
401 | --------------------
402 |
403 | ### New Features
404 |
405 | - Initial version for Debian
406 |
407 | ### Bug Fixes
408 |
409 | - none
410 |
411 | ### Other Changes
412 |
413 | - none
414 |
415 | [1.6.4] - 2022-01-10
416 | --------------------
417 |
418 | ### New Features
419 |
420 | - none
421 |
422 | ### Bug Fixes
423 |
424 | - Fix an issue if a service is listed by service\_facts that does not have the 'status' property defined
425 |
426 | ### Other Changes
427 |
428 | - bump tox-lsr version to 2.8.3
429 | - change recursive role symlink to individual role dir symlinks
430 |
431 | [1.6.3] - 2021-11-22
432 | --------------------
433 |
434 | ### New Features
435 |
436 | - none
437 |
438 | ### Bug Fixes
439 |
440 | - evaluate is\_ntp\_default as boolean, not string
441 | - reject services which have a status == not-found
442 | - also reject masked and failed services
443 |
444 | ### Other Changes
445 |
446 | - update tox-lsr version to 2.8.0
447 |
448 | [1.6.2] - 2021-11-08
449 | --------------------
450 |
451 | ### New Features
452 |
453 | - make role work with ansible-core-2.11 ansible-lint and ansible-test
454 |
455 | ### Bug Fixes
456 |
457 | - none
458 |
459 | ### Other Changes
460 |
461 | - update tox-lsr version to 2.7.1
462 | - support python 39, ansible-core 2.12, ansible-plugin-scan
463 | - Check port state in PTP tests
464 |
465 | [1.6.1] - 2021-09-21
466 | --------------------
467 |
468 | ### New Features
469 |
470 | - replace json\_query with selectattr/map
471 |
472 | ### Bug Fixes
473 |
474 | - Use {{ ansible\_managed | comment }} to fix multi-line ansible\_managed
475 |
476 | ### Other Changes
477 |
478 | - use apt-get install -y
479 | - use tox-lsr version 2.5.1
480 |
481 | [1.6.0] - 2021-08-10
482 | --------------------
483 |
484 | ### New Features
485 |
486 | - Raise supported Ansible version to 2.9
487 |
488 | ### Bug Fixes
489 |
490 | - none
491 |
492 | ### Other Changes
493 |
494 | - none
495 |
496 | [1.5.0] - 2021-06-03
497 | --------------------
498 |
499 | ### New Features
500 |
501 | - Add NTS support
502 |
503 | ### Bug Fixes
504 |
505 | - none
506 |
507 | ### Other Changes
508 |
509 | - none
510 |
511 | [1.4.1] - 2021-05-27
512 | --------------------
513 |
514 | ### New Features
515 |
516 | - none
517 |
518 | ### Bug Fixes
519 |
520 | - none
521 |
522 | ### Other Changes
523 |
524 | - CI: Add support for RHEL-9
525 |
526 | [1.4.0] - 2021-05-06
527 | --------------------
528 |
529 | ### New Features
530 |
531 | - use public: true to expose role parameters; ansible 2.8
532 | - Add hybrid\_e2e option to PTP domain
533 |
534 | ### Bug Fixes
535 |
536 | - Cleaning up ansible-lint errors except 301 and 303.
537 | - Fix ansible-test errors
538 |
539 | ### Other Changes
540 |
541 | - tag tests with slow
542 | - Remove python-26 environment from tox testing
543 | - update to tox-lsr 2.4.0 - add support for ansible-test with docker
544 |
545 | [1.3.0] - 2021-02-11
546 | --------------------
547 |
548 | ### New Features
549 |
550 | - Support chrony configuration in Fedora 33
551 | - Add support for HW timestamping with NTP
552 | - add timesync\_chrony\_custom\_settings variable for free-form local configs
553 |
554 | ### Bug Fixes
555 |
556 | - Fix centos6 repos; use standard centos images; add centos8
557 | - Fix package versions
558 |
559 | ### Other Changes
560 |
561 | - use tox-lsr 2.2.0
562 | - use molecule v3, drop v2
563 | - remove ansible 2.7 support from molecule
564 | - use tox for ansible-lint instead of molecule
565 | - use new tox-lsr plugin
566 | - use github actions instead of travis
567 |
568 | [1.2.0] - 2020-11-02
569 | --------------------
570 |
571 | ### New Features
572 |
573 | - Add option to configure max distance
574 | - Use service\_facts instead of chkconfig/systemctl
575 |
576 | ### Bug Fixes
577 |
578 | - none
579 |
580 | ### Other Changes
581 |
582 | - add jmespath as dependency for molecule
583 | - lock ansible-lint version at 4.3.5; suppress role name lint warning
584 | - sync collections related changes from template to timesync role
585 | - Lock ansible-lint on version 4.2.0
586 |
587 | [1.1.0] - 2020-08-12
588 | --------------------
589 |
590 | ### New Features
591 |
592 | - Remove ignore\_errors for Disable services tasks
593 |
594 | ### Bug Fixes
595 |
596 | - bug with current implementation of platform/version …
597 | - add support for tox; fix yamllint issues
598 | - use molecule v2
599 | - Fix check mode
600 | - Enable line-length check. Fix found issues.
601 |
602 | ### Other Changes
603 |
604 | - Synchronize files from linux-system-roles/template
605 | - sync with latest template including shellcheck
606 |
607 | [1.0.2] - 2019-06-13
608 | --------------------
609 |
610 | ### New Features
611 |
612 | - Use linux-system-roles.timesync as name for role
613 | - Use `is version` instead of `|version_compare`
614 | - Add empty timesync\_ntp\_provider to defaults
615 |
616 | ### Bug Fixes
617 |
618 | - Remove unused/now invalid semaphore config
619 | - Fixes for syntax problems found by Molecule
620 | - Fix yamllint error
621 | - Fix role to work in check mode
622 |
623 | ### Other Changes
624 |
625 | - Add default vars test
626 | - Run tests\_default both in normal and in check mode
627 | - use yaml syntax
628 | - Configure Molecule and Travis CI \(this PR should trigger build in CI\)
629 | - Add example playbooks
630 | - Add provision file to tests
631 | - Add test for setting the default NTP provider for OS release
632 |
633 | [1.0.1] - 2018-08-21
634 | --------------------
635 |
636 | ### New Features
637 |
638 | - none
639 |
640 | ### Bug Fixes
641 |
642 | - none
643 |
644 | ### Other Changes
645 |
646 | - Update Galaxy tags.
647 |
648 | [1.0.0] - 2018-08-21
649 | --------------------
650 |
651 | ### Initial Release
652 |
--------------------------------------------------------------------------------
/COPYING:
--------------------------------------------------------------------------------
1 | Copyright (c) 2017 Red Hat, Inc.
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
20 |
--------------------------------------------------------------------------------
/README-ansible.md:
--------------------------------------------------------------------------------
1 | # Introduction to Ansible for Linux System Roles
2 |
3 | If you are not familiar with Ansible, please see
4 | [Introduction to Ansible for Linux System Roles](https://linux-system-roles.github.io/documentation/intro-to-ansible-for-system-roles.html),
5 | where many useful links are presented.
6 |
--------------------------------------------------------------------------------
/README-ostree.md:
--------------------------------------------------------------------------------
1 | # rpm-ostree
2 |
3 | The role supports running on [rpm-ostree](https://coreos.github.io/rpm-ostree/)
4 | systems. The primary issue is that the `/usr` filesystem is read-only, and the
5 | role cannot install packages. Instead, it will just verify that the necessary
6 | packages and any other `/usr` files are pre-installed. The role will change the
7 | package manager to one that is compatible with `rpm-ostree` systems.
8 |
9 | ## Building
10 |
11 | To build an ostree image for a particular operating system distribution and
12 | version, use the script `.ostree/get_ostree_data.sh` to get the list of
13 | packages. If the role uses other system roles, then the script will include the
14 | packages for the other roles in the list it outputs. The list of packages will
15 | be sorted in alphanumeric order.
16 |
17 | Usage:
18 |
19 | ```bash
20 | .ostree/get_ostree_data.sh packages runtime DISTRO-VERSION FORMAT
21 | ```
22 |
23 | `DISTRO-VERSION` is in the format that Ansible uses for `ansible_distribution`
24 | and `ansible_distribution_version` - for example, `Fedora-38`, `CentOS-8`,
25 | `RedHat-9.4`
26 |
27 | `FORMAT` is one of `toml`, `json`, `yaml`, `raw`
28 |
29 | * `toml` - each package in a TOML `[[packages]]` element
30 |
31 | ```toml
32 | [[packages]]
33 | name = "package-a"
34 | version = "*"
35 | [[packages]]
36 | name = "package-b"
37 | version = "*"
38 | ...
39 | ```
40 |
41 | * `yaml` - a YAML list of packages
42 |
43 | ```yaml
44 | - package-a
45 | - package-b
46 | ...
47 | ```
48 |
49 | * `json` - a JSON list of packages
50 |
51 | ```json
52 | ["package-a","package-b",...]
53 | ```
54 |
55 | * `raw` - a plain text list of packages, one per line
56 |
57 | ```bash
58 | package-a
59 | package-b
60 | ...
61 | ```
62 |
63 | What format you choose depends on which image builder you are using. For
64 | example, if you are using something based on
65 | [osbuild-composer](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html-single/composing_installing_and_managing_rhel_for_edge_images/index#creating-an-image-builder-blueprint-for-a-rhel-for-edge-image-using-the-command-line-interface_composing-a-rhel-for-edge-image-using-image-builder-command-line),
66 | you will probably want to use the `toml` output format.
67 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # timesync
2 |
3 | [](https://github.com/linux-system-roles/timesync/actions/workflows/ansible-lint.yml) [](https://github.com/linux-system-roles/timesync/actions/workflows/ansible-test.yml) [](https://github.com/linux-system-roles/timesync/actions/workflows/codespell.yml) [](https://github.com/linux-system-roles/timesync/actions/workflows/markdownlint.yml) [](https://github.com/linux-system-roles/timesync/actions/workflows/qemu-kvm-integration-tests.yml) [](https://github.com/linux-system-roles/timesync/actions/workflows/shellcheck.yml) [](https://github.com/linux-system-roles/timesync/actions/workflows/tft.yml) [](https://github.com/linux-system-roles/timesync/actions/workflows/tft_citest_bad.yml) [](https://github.com/linux-system-roles/timesync/actions/workflows/woke.yml)
4 |
5 | This role installs and configures an NTP and/or PTP implementation to operate
6 |
7 | as an NTP client and/or PTP slave in order to synchronize the system clock with
8 |
9 | NTP servers and/or grandmasters in PTP domains. Supported NTP/PTP
10 | implementations are chrony, ntp (the reference implementation) and linuxptp.
11 |
12 | ## Warning
13 |
14 | The role replaces the configuration of the given or detected provider
15 | service on the managed host. Previous settings will be lost, even if
16 | they are not specified in the role variables (no attempt is made to
17 | preserve or merge the previous settings, the configuration files are
18 | replaced entirely). The only setting which is preserved is the choice
19 | of provider if `timesync_ntp_provider` is not defined (see the
20 | description of this variable below).
21 |
22 | ## Requirements
23 |
24 | See below
25 |
26 | ### Collection requirements
27 |
28 | In order to manage `rpm-ostree` systems, the role requires modules from external
29 | collections. Use the following command to install them:
30 |
31 | ```bash
32 | ansible-galaxy collection install -vv -r meta/collection-requirements.yml
33 | ```
34 |
35 | ## Role Variables
36 |
37 | The variables that can be passed to this role are as follows:
38 |
39 | ```yaml
40 | # List of NTP servers
41 | timesync_ntp_servers:
42 | - hostname: foo.example.com # Hostname or address of the server
43 | minpoll: 4 # Minimum polling interval (default 6)
44 | maxpoll: 8 # Maximum polling interval (default 10)
45 | iburst: true # Flag enabling fast initial synchronization
46 | # (default false)
47 | pool: false # Flag indicating that each resolved address
48 | # of the hostname is a separate NTP server
49 | # (default false)
50 | nts: false # Flag enabling Network Time Security (NTS)
51 | # authentication mechanism (default false,
52 | # supported only with chrony >= 4.0)
53 | prefer: false # Flag marking the source to be preferred for
54 | # synchronization over other sources
55 | # (default false)
56 | trust: false # Flag marking the source to be trusted over
57 | # sources that don't have this flag
58 | # (default false)
59 | xleave: false # Flag enabling interleaved mode (default false)
60 | filter: 1 # Number of NTP measurements per clock update
61 | # (default 1)
62 |
63 | # List of PTP domains
64 | timesync_ptp_domains:
65 | - number: 0 # PTP domain number
66 | interfaces: [eth0] # List of interfaces in the domain
67 | delay: 0.000010 # Assumed maximum network delay to the
68 | # grandmaster in seconds # wokeignore:rule=master
69 | # (default 100 microsecond)
70 | transport: UDPv4 # Network transport: UDPv4, UDPv6, L2
71 | # (default UDPv4)
72 | udp_ttl: 1 # TTL for UDPv4 and UDPv6 transports
73 | # (default 1)
74 | hybrid_e2e: false # Flag enabling unicast end-to-end delay
75 | # requests (default false)
76 |
77 | # Flag enabling use of NTP servers provided by DHCP (default false)
78 | timesync_dhcp_ntp_servers: false
79 |
80 | # Minimum offset of the clock which can be corrected by stepping (default is
81 | # specific to NTP/PTP implementation: chrony 1.0, ntp 0.128, linuxptp 0.00002).
82 | # Zero threshold disables all steps.
83 | timesync_step_threshold: 1.0
84 |
85 | # Maximum root distance to accept measurements from NTP servers
86 | # Set to 0 to use provider default
87 | timesync_max_distance: 0
88 |
89 | # Minimum number of selectable time sources required to allow synchronization
90 | # of the clock (default 1)
91 | timesync_min_sources: 1
92 |
93 | # List of interfaces which should have hardware timestamping enabled for NTP
94 | # (default empty list). As a special value, '*' enables the timestamping on all
95 | # interfaces that support it.
96 | timesync_ntp_hwts_interfaces: ["*"]
97 |
98 | # Name of the package which should be installed and configured for NTP.
99 | # Possible values are "chrony" and "ntp". If not defined, the currently active
100 | # or enabled service will be configured. If no service is active or enabled, a
101 | # package specific to the system and its version will be selected.
102 | timesync_ntp_provider: chrony
103 |
104 | # Sometimes administrators might need extended configurations for chrony which
105 | # are not covered by the predefined settings provided by this role.
106 | # 'timesync_chrony_custom_settings' allows to define a list of custom settings
107 | # for the chrony.conf file, by providing a list of settings. As an example,
108 | # for debugging, one might need to log measurements, statistics and tracking.
109 | # This information is usually stored in the /var/log/chrony directory. For
110 | # that, one needs to define two different settings (logdir and log), as
111 | # follows:
112 | timesync_chrony_custom_settings:
113 | - "logdir /var/log/chrony"
114 | - "log measurements statistics tracking"
115 |
116 | # This variable is applicable only for transactional update systems.
117 | # If a transactional update requires a reboot, the role will proceed with the
118 | # reboot if `timesync_transactional_update_reboot_ok` is set to `true`. If set
119 | # to `false`, the role will notify the user that a reboot is required, allowing
120 | # for custom handling of the reboot requirement. If this variable is not set,
121 | # the role will fail to ensure the reboot requirement is not overlooked.
122 | # For non-transactional update systems, this variable is ignored.
123 | timesync_transactional_update_reboot_ok: true
124 |
125 | # This option is useful on systems where IPv6 or IPv4 are disabled.
126 | # chronyd will work on a IPv6-disabled host without -4, but it logs error messages
127 | # when binding to the IPv6 sockets fails. Adding the -4 option disables those sockets
128 | # and there are no error messages. It's also useful to prevent the client from using
129 | # IPv6 servers when IPv4 is known to work better (e.g. IPv6 over a tunnel).
130 | # Corresponds to the `-4` and `-6` OPTIONS for chronyd and ntpd. Values are:
131 | # * IPv4 - use only IPv4
132 | # * IPv6 - use only IPv6
133 | # * all - use both IPv4 and IPv6
134 | # Default is all
135 | timesync_ntp_ip_family: all
136 | ```
137 |
138 | ## Example Playbooks
139 |
140 | Install and configure ntp to synchronize the system clock with three NTP servers:
141 |
142 | ```yaml
143 | - name: Manage timesync with 3 servers
144 | hosts: targets
145 | vars:
146 | timesync_ntp_servers:
147 | - hostname: foo.example.com
148 | iburst: true
149 | - hostname: bar.example.com
150 | iburst: true
151 | - hostname: baz.example.com
152 | iburst: true
153 | roles:
154 | - linux-system-roles.timesync
155 | ```
156 |
157 | Install and configure linuxptp to synchronize the system clock with a
158 |
159 | grandmaster in PTP domain number 0, which is accessible on interface eth0:
160 |
161 | ```yaml
162 | - name: Manage timesync in PTP domain 0, interface eth0
163 | hosts: targets
164 | vars:
165 | timesync_ptp_domains:
166 | - number: 0
167 | interfaces: [eth0]
168 | roles:
169 | - linux-system-roles.timesync
170 | ```
171 |
172 | Install and configure chrony and linuxptp to synchronize the system clock with
173 | multiple NTP servers and PTP domains for a highly accurate and resilient
174 | synchronization:
175 |
176 | ```yaml
177 | - name: Manage multiple NTP servers and PTP domains
178 | hosts: targets
179 | vars:
180 | timesync_ntp_servers:
181 | - hostname: foo.example.com
182 | maxpoll: 6
183 | - hostname: bar.example.com
184 | maxpoll: 6
185 | - hostname: baz.example.com
186 | maxpoll: 6
187 | timesync_ptp_domains:
188 | - number: 0
189 | interfaces: [eth0, eth1]
190 | transport: L2
191 | delay: 0.000010
192 | - number: 1
193 | interfaces: [eth2]
194 | transport: UDPv4
195 | delay: 0.000010
196 | roles:
197 | - linux-system-roles.timesync
198 | ```
199 |
200 | Install and configure chrony with multiple NTP servers and custom advanced
201 | settings: log `measurements`, `statistics` and `tracking`
202 | into `/var/log/chrony`:
203 |
204 | ```yaml
205 | - name: Manage with custom advanced settings
206 | hosts: targets
207 | vars:
208 | timesync_ntp_servers:
209 | - hostname: foo.example.com
210 | - hostname: bar.example.com
211 | - hostname: baz.example.com
212 | timesync_chrony_custom_settings:
213 | - "logdir /var/log/chrony"
214 | - "log measurements statistics tracking"
215 | roles:
216 | - linux-system-roles.timesync
217 | ```
218 |
219 | ## rpm-ostree
220 |
221 | See README-ostree.md
222 |
--------------------------------------------------------------------------------
/ansible_pytest_extra_requirements.txt:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: MIT
2 |
3 | # ansible and dependencies for all supported platforms
4 | ansible ; python_version > "2.6"
5 | idna<2.8 ; python_version < "2.7"
6 | PyYAML<5.1 ; python_version < "2.7"
7 |
--------------------------------------------------------------------------------
/contributing.md:
--------------------------------------------------------------------------------
1 | # Contributing to the timesync Linux System Role
2 |
3 | ## Where to start
4 |
5 | The first place to go is [Contribute](https://linux-system-roles.github.io/contribute.html).
6 | This has all of the common information that all role developers need:
7 |
8 | * Role structure and layout
9 | * Development tools - How to run tests and checks
10 | * Ansible recommended practices
11 | * Basic git and github information
12 | * How to create git commits and submit pull requests
13 |
14 | **Bugs and needed implementations** are listed on
15 | [Github Issues](https://github.com/linux-system-roles/timesync/issues).
16 | Issues labeled with
17 | [**help wanted**](https://github.com/linux-system-roles/timesync/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22)
18 | are likely to be suitable for new contributors!
19 |
20 | **Code** is managed on [Github](https://github.com/linux-system-roles/timesync), using
21 | [Pull Requests](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests).
22 |
--------------------------------------------------------------------------------
/custom_requirements.txt:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: MIT
2 |
3 | # Write requirements for running your custom commands in tox here:
4 |
--------------------------------------------------------------------------------
/defaults/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | timesync_ntp_servers: []
3 | timesync_ptp_domains: []
4 | timesync_dhcp_ntp_servers: false
5 | timesync_step_threshold: -1.0
6 | timesync_min_sources: 1
7 | timesync_ntp_hwts_interfaces: []
8 | timesync_ntp_provider: ""
9 | timesync_max_distance: 0
10 | timesync_transactional_update_reboot_ok: null
11 | # options are all, IPv4, IPv6
12 | # default is none which is platform default
13 | timesync_ntp_ip_family: ""
14 |
--------------------------------------------------------------------------------
/examples/multiple-ntp-servers.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Example with multiple servers
3 | hosts: "{{ targets }}"
4 | vars:
5 | timesync_ntp_servers:
6 | - hostname: 0.pool.ntp.org
7 | iburst: true
8 | - hostname: 1.pool.ntp.org
9 | iburst: true
10 | - hostname: 2.pool.ntp.org
11 | iburst: true
12 | - hostname: 3.pool.ntp.org
13 | iburst: true
14 | roles:
15 | - linux-system-roles.timesync
16 |
--------------------------------------------------------------------------------
/examples/single-pool.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Example with single pool
3 | hosts: "{{ targets }}"
4 | vars:
5 | timesync_ntp_servers:
6 | - hostname: 2.pool.ntp.org
7 | pool: true
8 | iburst: true
9 | roles:
10 | - linux-system-roles.timesync
11 |
--------------------------------------------------------------------------------
/handlers/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Restart chronyd
3 | service:
4 | name: chronyd
5 | state: restarted
6 |
7 | - name: Restart ntpd
8 | service:
9 | name: ntpd
10 | state: restarted
11 |
12 | - name: Restart ptp4l
13 | service:
14 | name: ptp4l
15 | state: restarted
16 |
17 | - name: Restart phc2sys
18 | service:
19 | name: phc2sys
20 | state: restarted
21 |
22 | # wokeignore:rule=master
23 | - name: Restart timemaster
24 | service:
25 | # wokeignore:rule=master
26 | name: timemaster
27 | state: restarted
28 |
--------------------------------------------------------------------------------
/library/timesync_provider.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # WANT_JSON
3 |
4 | is_service_enabled() {
5 | local name runlevel prev_runlevel
6 | name="$1"
7 |
8 | # shellcheck disable=SC2034
9 | read -r prev_runlevel runlevel < <(runlevel)
10 |
11 | systemctl is-enabled "$name.service" &> /dev/null || \
12 | chkconfig --list "$name" 2>/dev/null | grep -q "$runlevel:on"
13 | }
14 |
15 | is_service_active() {
16 | local name=$1
17 |
18 | systemctl is-active "$name.service" &> /dev/null || \
19 | service "$name" status &>/dev/null
20 | }
21 |
22 | get_current_ntp_providers() {
23 | is_service_active chronyd || is_service_enabled chronyd && echo chrony
24 | is_service_active ntpd || is_service_enabled ntpd && echo ntp
25 | }
26 |
27 |
28 | current_ntp_providers=$(get_current_ntp_providers)
29 |
30 | ntp_provider_count=$(echo -n "$current_ntp_providers" | wc -w)
31 |
32 | case $ntp_provider_count in
33 | 0)
34 | ntp_provider_current=""
35 | ;;
36 | 1)
37 | ntp_provider_current=$current_ntp_providers
38 | ;;
39 | *)
40 | ntp_provider_current=""
41 | error_message="Multiple NTP providers are currently active/enabled."
42 | ;;
43 | esac
44 |
45 | if [ -z "$error_message" ]; then
46 | printf '{"ansible_facts": {"timesync_ntp_provider_current": "%s"}}' "$ntp_provider_current"
47 | else
48 | printf '{"failed": "True", "msg": "%s"}' "$error_message"
49 | fi
50 |
--------------------------------------------------------------------------------
/library/timesync_provider.yml:
--------------------------------------------------------------------------------
1 | DOCUMENTATION:
2 | module: timesync_provider
3 | short_description: Determine the timesync provider on the system
4 | version_added: "2.14.0"
5 | description:
6 | - "WARNING: Do not use this module directly! It is only for role internal use."
7 | - "Determine the timesync provider on the system and return it."
8 | options: {}
9 | author:
10 | - Miroslav Lichvar (@mlichvar)
11 | EXAMPLES: |-
12 | - name: Determine current NTP provider
13 | timesync_provider:
14 | RETURN:
15 | timesync_ntp_provider_current:
16 | description: Name of current provider e.g. chrony or ntp
17 | returned: success
18 | type: str
19 | sample: chrony
20 |
--------------------------------------------------------------------------------
/meta/collection-requirements.yml:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: MIT
2 | ---
3 | collections:
4 | - ansible.posix
5 |
--------------------------------------------------------------------------------
/meta/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | galaxy_info:
3 | author: Miroslav Lichvar
4 | description: Configure NTP and/or PTP
5 | company: Red Hat, Inc.
6 | license: MIT
7 | min_ansible_version: "2.9"
8 | platforms:
9 | - name: Fedora
10 | versions:
11 | - all
12 | - name: EL
13 | versions:
14 | - "6"
15 | - "7"
16 | - "8"
17 | - "9"
18 | galaxy_tags:
19 | - centos
20 | - chrony
21 | - el6
22 | - el7
23 | - el8
24 | - el9
25 | - el10
26 | - fedora
27 | - ntp
28 | - ntpd
29 | - ptp
30 | - redhat
31 | - rhel
32 | - system
33 | - time
34 |
--------------------------------------------------------------------------------
/molecule/default/Dockerfile.j2:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: MIT
2 | # Molecule managed
3 |
4 | {% if item.registry is defined %}
5 | FROM {{ item.registry.url }}/{{ item.image }}
6 | {% else %}
7 | FROM {{ item.image }}
8 | {% endif %}
9 |
10 | RUN set -euo pipefail; \
11 | pkgs="python sudo yum-plugin-ovl bash"; \
12 | if grep 'CentOS release 6' /etc/centos-release > /dev/null 2>&1; then \
13 | for file in /etc/yum.repos.d/CentOS-*.repo; do \
14 | if ! grep '^baseurl=.*vault[.]centos[.]org' "$file"; then \
15 | sed -i -e 's,^mirrorlist,#mirrorlist,' \
16 | -e 's,^#baseurl=,baseurl=,' \
17 | -e 's,mirror.centos.org/centos/$releasever,vault.centos.org/6.10,' \
18 | "$file"; \
19 | fi; \
20 | done; \
21 | pkgs="$pkgs upstart chkconfig initscripts"; \
22 | fi; \
23 | if [ $(command -v apt-get) ]; then apt-get update && apt-get install -y python sudo bash ca-certificates && apt-get clean; \
24 | elif [ $(command -v dnf) ]; then dnf makecache && dnf --assumeyes install python3 sudo python3-devel python3-dnf bash && dnf clean all; \
25 | elif [ $(command -v yum) ]; then yum makecache fast && yum install -y $pkgs && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && yum clean all; \
26 | elif [ $(command -v zypper) ]; then zypper refresh && zypper install -y python sudo bash python-xml && zypper clean -a; \
27 | elif [ $(command -v apk) ]; then apk update && apk add --no-cache python sudo bash ca-certificates; \
28 | elif [ $(command -v xbps-install) ]; then xbps-install -Syu && xbps-install -y python sudo bash ca-certificates && xbps-remove -O; fi
29 |
--------------------------------------------------------------------------------
/molecule/default/molecule.yml:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: MIT
2 | ---
3 | dependency:
4 | name: galaxy
5 | driver:
6 | name: ${LSR_MOLECULE_DRIVER:-docker}
7 | platforms:
8 | - name: centos-6
9 | image: registry.centos.org/centos:6
10 | volumes:
11 | - /sys/fs/cgroup:/sys/fs/cgroup:ro
12 | privileged: true
13 | command: /sbin/init
14 | - name: centos-7
15 | image: registry.centos.org/centos/systemd:latest
16 | volumes:
17 | - /sys/fs/cgroup:/sys/fs/cgroup:ro
18 | privileged: true
19 | command: /usr/lib/systemd/systemd --system
20 | - name: centos-8
21 | image: registry.centos.org/centos:8
22 | volumes:
23 | - /sys/fs/cgroup:/sys/fs/cgroup:ro
24 | privileged: true
25 | command: /usr/lib/systemd/systemd --system
26 | provisioner:
27 | name: ansible
28 | log: true
29 | playbooks:
30 | converge: ../../tests/tests_default.yml
31 | scenario:
32 | name: default
33 | test_sequence:
34 | - destroy
35 | - create
36 | - converge
37 | - idempotence
38 | - check
39 | - destroy
40 |
--------------------------------------------------------------------------------
/molecule_extra_requirements.txt:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: MIT
2 |
3 | # Write extra requirements for running molecule here:
4 |
--------------------------------------------------------------------------------
/plans/README-plans.md:
--------------------------------------------------------------------------------
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 [tft.yml](https://github.com/linux-system-roles/timesync/blob/main/.github/workflows/tft.yml) GitHub workflow.
4 |
5 | The `plans/test_playbooks_parallel.fmf` plan is a test plan that runs test playbooks in parallel on multiple managed nodes.
6 | `plans/test_playbooks_parallel.fmf` is generated centrally from `https://github.com/linux-system-roles/.github/`.
7 | The automation calculates the number of managed nodes to provision with this formula:
8 |
9 | ```plain
10 | number-of-test-playbooks / 10 + 1
11 | ```
12 |
13 | The `plans/test_playbooks_parallel.fmf` plan does the following steps:
14 |
15 | 1. Provisions systems to be used as a control node and as managed nodes.
16 | 2. Does the required preparation on systems.
17 | 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).
18 |
19 | The [tft.yml](https://github.com/linux-system-roles/timesync/blob/main/.github/workflows/tft.yml) workflow runs the above plan and uploads the results to our Fedora storage for public access.
20 | This workflow uses Testing Farm's Github Action [Schedule tests on Testing Farm](https://github.com/marketplace/actions/schedule-tests-on-testing-farm).
21 |
22 | ## Running Tests
23 |
24 | You can run tests locally with the `tmt try` cli or remotely in Testing Farm.
25 |
26 | ### Running Tests Locally
27 |
28 | 1. Install `tmt` as described in [Installation](https://tmt.readthedocs.io/en/stable/stories/install.html).
29 | 2. Change to the role repository directory.
30 | 3. Modify `plans/test_playbooks_parallel.fmf` to suit your requirements:
31 | 1. Due to [issue #3138](https://github.com/teemtee/tmt/issues/3138), comment out all managed nodes except for one.
32 | 2. Optionally modify environment variables to, e.g. run only specified test playbooks by modifying `SYSTEM_ROLES_ONLY_TESTS`.
33 | 4. Enter `tmt try -p plans/test_playbooks_parallel `.
34 | This command identifies the `plans/test_playbooks_parallel.fmf` plan and provisions local VMs, a control node and a managed node.
35 | 5. `tmt try` is in development and does not identify tests from URL automatically, so after provisioning the machines, you must type `t`, `p`, `t` from the interactive prompt to identify tests, run preparation steps, and run the tests.
36 |
37 | ### Running in Testing Farm
38 |
39 | 1. Install `testing-farm` as described in [Installation](https://gitlab.com/testing-farm/cli/-/blob/main/README.adoc#user-content-installation).
40 | 2. Change to the role repository directory.
41 | 3. If you want to run tests with edits in your branch, you need to commit and push changes first to some branch.
42 | 4. You can uncomment "Inject your ssh public key to test systems" discover step in the plan if you want to troubleshoot tests by SSHing into test systems in Testing Farm.
43 | 5. Enter `testing-farm request`.
44 | Edit to your needs.
45 |
46 | ```bash
47 | $ TESTING_FARM_API_TOKEN= \
48 | testing-farm request --pipeline-type="tmt-multihost" \
49 | --plan-filter="tag:playbooks_parallel" \
50 | --git-url "https://github.com//timesync" \
51 | --git-ref "" \
52 | --compose CentOS-Stream-9 \
53 | -e "SYSTEM_ROLES_ONLY_TESTS=tests_default.yml" \
54 | --no-wait
55 | ```
56 |
--------------------------------------------------------------------------------
/plans/test_playbooks_parallel.fmf:
--------------------------------------------------------------------------------
1 | summary: A general test for a system role
2 | tag: playbooks_parallel
3 | provision:
4 | # TF uses `how: artemis`, and `tmt try`` uses `how: virtual`.
5 | # Hence there is no need to define `how` explicitly.
6 | - name: control-node1
7 | role: control_node
8 | - name: managed-node1
9 | role: managed_node
10 | - name: managed-node2
11 | role: managed_node
12 | - name: managed-node3
13 | role: managed_node
14 | environment:
15 | SR_ANSIBLE_VER: 2.17
16 | SR_REPO_NAME: timesync
17 | SR_PYTHON_VERSION: 3.12
18 | SR_ONLY_TESTS: "" # tests_default.yml
19 | SR_TEST_LOCAL_CHANGES: true
20 | SR_PR_NUM: ""
21 | SR_LSR_USER: ""
22 | SR_LSR_DOMAIN: ""
23 | SR_LSR_SSH_KEY: ""
24 | SR_ARTIFACTS_DIR: ""
25 | SR_ARTIFACTS_URL: ""
26 | SR_TFT_DEBUG: false
27 | prepare:
28 | - name: Use vault.centos.org repos (CS 7, 8 EOL workaround)
29 | script: |
30 | if grep -q 'CentOS Stream release 8' /etc/redhat-release; then
31 | sed -i '/^mirror/d;s/#\(baseurl=http:\/\/\)mirror/\1vault/' /etc/yum.repos.d/*.repo
32 | fi
33 | if grep -q 'CentOS Linux release 7.9' /etc/redhat-release; then
34 | sed -i '/^mirror/d;s/#\?\(baseurl=http:\/\/\)mirror/\1vault/' /etc/yum.repos.d/*.repo
35 | fi
36 | # Replace with feature: epel: enabled once https://github.com/teemtee/tmt/pull/3128 is merged
37 | - name: Enable epel to install beakerlib
38 | script: |
39 | # CS 10 and Fedora doesn't require epel
40 | if grep -q -e 'CentOS Stream release 10' -e 'Fedora release' /etc/redhat-release; then
41 | exit 0
42 | fi
43 | yum install epel-release yum-utils -y
44 | yum-config-manager --enable epel epel-debuginfo epel-source
45 | discover:
46 | - name: Prepare managed node
47 | how: fmf
48 | where: managed_node
49 | filter: tag:prep_managed_node
50 | url: https://github.com/linux-system-roles/tft-tests
51 | ref: main
52 | - name: Run test playbooks from control_node
53 | how: fmf
54 | where: control_node
55 | filter: tag:test_playbooks
56 | url: https://github.com/linux-system-roles/tft-tests
57 | ref: main
58 | # Uncomment this step for troubleshooting
59 | # This is required because currently testing-farm cli doesn't support running multi-node plans
60 | # You can set ID_RSA_PUB in the environment section above to your public key to distribute it to nodes
61 | # - name: Inject your ssh public key to test systems
62 | # how: fmf
63 | # where: control_node
64 | # filter: tag:reserve_system
65 | # url: https://github.com/linux-system-roles/tft-tests
66 | # ref: main
67 | execute:
68 | how: tmt
69 |
--------------------------------------------------------------------------------
/pylint_extra_requirements.txt:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: MIT
2 |
3 | # Write extra requirements for running pylint here:
4 |
--------------------------------------------------------------------------------
/pylintrc:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: MIT
2 |
3 | # This file was generated using `pylint --generate-rcfile > pylintrc` command.
4 | [MASTER]
5 |
6 | # A comma-separated list of package or module names from where C extensions may
7 | # be loaded. Extensions are loading into the active Python interpreter and may
8 | # run arbitrary code
9 | extension-pkg-whitelist=
10 |
11 | # Add files or directories to the blacklist. They should be base names, not
12 | # paths.
13 | ignore=.git,.tox
14 |
15 | # Add files or directories matching the regex patterns to the blacklist. The
16 | # regex matches against base names, not paths.
17 | ignore-patterns=
18 |
19 | # Python code to execute, usually for sys.path manipulation such as
20 | # pygtk.require().
21 | #init-hook=
22 |
23 | # Use multiple processes to speed up Pylint.
24 | jobs=1
25 |
26 | # List of plugins (as comma separated values of python modules names) to load,
27 | # usually to register additional checkers.
28 | load-plugins=
29 |
30 | # Pickle collected data for later comparisons.
31 | persistent=yes
32 |
33 | # Specify a configuration file.
34 | #rcfile=
35 |
36 | # When enabled, pylint would attempt to guess common misconfiguration and emit
37 | # user-friendly hints instead of false-positive error messages
38 | suggestion-mode=yes
39 |
40 | # Allow loading of arbitrary C extensions. Extensions are imported into the
41 | # active Python interpreter and may run arbitrary code.
42 | unsafe-load-any-extension=no
43 |
44 |
45 | [MESSAGES CONTROL]
46 |
47 | # Only show warnings with the listed confidence levels. Leave empty to show
48 | # all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
49 | confidence=
50 |
51 | # Disable the message, report, category or checker with the given id(s). You
52 | # can either give multiple identifiers separated by comma (,) or put this
53 | # option multiple times (only on the command line, not in the configuration
54 | # file where it should appear only once).You can also use "--disable=all" to
55 | # disable everything first and then re-enable specific checks. For example, if
56 | # you want to run only the similarities checker, you can use "--disable=all
57 | # --enable=similarities". If you want to run only the classes checker, but have
58 | # no Warning level messages displayed, use"--disable=all --enable=classes
59 | # --disable=W"
60 | disable=wrong-import-position
61 | #disable=print-statement,
62 | # parameter-unpacking,
63 | # unpacking-in-except,
64 | # old-raise-syntax,
65 | # backtick,
66 | # long-suffix,
67 | # old-ne-operator,
68 | # old-octal-literal,
69 | # import-star-module-level,
70 | # non-ascii-bytes-literal,
71 | # raw-checker-failed,
72 | # bad-inline-option,
73 | # locally-disabled,
74 | # locally-enabled,
75 | # file-ignored,
76 | # suppressed-message,
77 | # useless-suppression,
78 | # deprecated-pragma,
79 | # apply-builtin,
80 | # basestring-builtin,
81 | # buffer-builtin,
82 | # cmp-builtin,
83 | # coerce-builtin,
84 | # execfile-builtin,
85 | # file-builtin,
86 | # long-builtin,
87 | # raw_input-builtin,
88 | # reduce-builtin,
89 | # standarderror-builtin,
90 | # unicode-builtin,
91 | # xrange-builtin,
92 | # coerce-method,
93 | # delslice-method,
94 | # getslice-method,
95 | # setslice-method,
96 | # no-absolute-import,
97 | # old-division,
98 | # dict-iter-method,
99 | # dict-view-method,
100 | # next-method-called,
101 | # metaclass-assignment,
102 | # indexing-exception,
103 | # raising-string,
104 | # reload-builtin,
105 | # oct-method,
106 | # hex-method,
107 | # nonzero-method,
108 | # cmp-method,
109 | # input-builtin,
110 | # round-builtin,
111 | # intern-builtin,
112 | # unichr-builtin,
113 | # map-builtin-not-iterating,
114 | # zip-builtin-not-iterating,
115 | # range-builtin-not-iterating,
116 | # filter-builtin-not-iterating,
117 | # using-cmp-argument,
118 | # eq-without-hash,
119 | # div-method,
120 | # idiv-method,
121 | # rdiv-method,
122 | # exception-message-attribute,
123 | # invalid-str-codec,
124 | # sys-max-int,
125 | # bad-python3-import,
126 | # deprecated-string-function,
127 | # deprecated-str-translate-call,
128 | # deprecated-itertools-function,
129 | # deprecated-types-field,
130 | # next-method-defined,
131 | # dict-items-not-iterating,
132 | # dict-keys-not-iterating,
133 | # dict-values-not-iterating
134 |
135 | # Enable the message, report, category or checker with the given id(s). You can
136 | # either give multiple identifier separated by comma (,) or put this option
137 | # multiple time (only on the command line, not in the configuration file where
138 | # it should appear only once). See also the "--disable" option for examples.
139 | enable=c-extension-no-member
140 |
141 |
142 | [REPORTS]
143 |
144 | # Python expression which should return a note less than 10 (10 is the highest
145 | # note). You have access to the variables errors warning, statement which
146 | # respectively contain the number of errors / warnings messages and the total
147 | # number of statements analyzed. This is used by the global evaluation report
148 | # (RP0004).
149 | evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
150 |
151 | # Template used to display messages. This is a python new-style format string
152 | # used to format the message information. See doc for all details
153 | #msg-template=
154 |
155 | # Set the output format. Available formats are text, parseable, colorized, json
156 | # and msvs (visual studio).You can also give a reporter class, eg
157 | # mypackage.mymodule.MyReporterClass.
158 | output-format=text
159 |
160 | # Tells whether to display a full report or only the messages
161 | reports=no
162 |
163 | # Activate the evaluation score.
164 | score=yes
165 |
166 |
167 | [REFACTORING]
168 |
169 | # Maximum number of nested blocks for function / method body
170 | max-nested-blocks=5
171 |
172 | # Complete name of functions that never returns. When checking for
173 | # inconsistent-return-statements if a never returning function is called then
174 | # it will be considered as an explicit return statement and no message will be
175 | # printed.
176 | never-returning-functions=optparse.Values,sys.exit
177 |
178 |
179 | [LOGGING]
180 |
181 | # Logging modules to check that the string format arguments are in logging
182 | # function parameter format
183 | logging-modules=logging
184 |
185 |
186 | [TYPECHECK]
187 |
188 | # List of decorators that produce context managers, such as
189 | # contextlib.contextmanager. Add to this list to register other decorators that
190 | # produce valid context managers.
191 | contextmanager-decorators=contextlib.contextmanager
192 |
193 | # List of members which are set dynamically and missed by pylint inference
194 | # system, and so shouldn't trigger E1101 when accessed. Python regular
195 | # expressions are accepted.
196 | generated-members=
197 |
198 | # Tells whether missing members accessed in mixin class should be ignored. A
199 | # mixin class is detected if its name ends with "mixin" (case insensitive).
200 | ignore-mixin-members=yes
201 |
202 | # This flag controls whether pylint should warn about no-member and similar
203 | # checks whenever an opaque object is returned when inferring. The inference
204 | # can return multiple potential results while evaluating a Python object, but
205 | # some branches might not be evaluated, which results in partial inference. In
206 | # that case, it might be useful to still emit no-member and other checks for
207 | # the rest of the inferred objects.
208 | ignore-on-opaque-inference=yes
209 |
210 | # List of class names for which member attributes should not be checked (useful
211 | # for classes with dynamically set attributes). This supports the use of
212 | # qualified names.
213 | ignored-classes=optparse.Values,thread._local,_thread._local
214 |
215 | # List of module names for which member attributes should not be checked
216 | # (useful for modules/projects where namespaces are manipulated during runtime
217 | # and thus existing member attributes cannot be deduced by static analysis. It
218 | # supports qualified module names, as well as Unix pattern matching.
219 | ignored-modules=
220 |
221 | # Show a hint with possible names when a member name was not found. The aspect
222 | # of finding the hint is based on edit distance.
223 | missing-member-hint=yes
224 |
225 | # The minimum edit distance a name should have in order to be considered a
226 | # similar match for a missing member name.
227 | missing-member-hint-distance=1
228 |
229 | # The total number of similar names that should be taken in consideration when
230 | # showing a hint for a missing member.
231 | missing-member-max-choices=1
232 |
233 |
234 | [FORMAT]
235 |
236 | # Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
237 | expected-line-ending-format=
238 |
239 | # Regexp for a line that is allowed to be longer than the limit.
240 | ignore-long-lines=^\s*(# )??$
241 |
242 | # Number of spaces of indent required inside a hanging or continued line.
243 | indent-after-paren=4
244 |
245 | # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
246 | # tab).
247 | indent-string=' '
248 |
249 | # Maximum number of characters on a single line.
250 | max-line-length=88
251 |
252 | # Maximum number of lines in a module
253 | max-module-lines=1000
254 |
255 | # List of optional constructs for which whitespace checking is disabled. `dict-
256 | # separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
257 | # `trailing-comma` allows a space between comma and closing bracket: (a, ).
258 | # `empty-line` allows space-only lines.
259 | no-space-check=trailing-comma,
260 | dict-separator
261 |
262 | # Allow the body of a class to be on the same line as the declaration if body
263 | # contains single statement.
264 | single-line-class-stmt=no
265 |
266 | # Allow the body of an if to be on the same line as the test if there is no
267 | # else.
268 | single-line-if-stmt=no
269 |
270 |
271 | [SPELLING]
272 |
273 | # Limits count of emitted suggestions for spelling mistakes
274 | max-spelling-suggestions=4
275 |
276 | # Spelling dictionary name. Available dictionaries: none. To make it working
277 | # install python-enchant package.
278 | spelling-dict=
279 |
280 | # List of comma separated words that should not be checked.
281 | spelling-ignore-words=
282 |
283 | # A path to a file that contains private dictionary; one word per line.
284 | spelling-private-dict-file=
285 |
286 | # Tells whether to store unknown words to indicated private dictionary in
287 | # --spelling-private-dict-file option instead of raising a message.
288 | spelling-store-unknown-words=no
289 |
290 |
291 | [SIMILARITIES]
292 |
293 | # Ignore comments when computing similarities.
294 | ignore-comments=yes
295 |
296 | # Ignore docstrings when computing similarities.
297 | ignore-docstrings=yes
298 |
299 | # Ignore imports when computing similarities.
300 | ignore-imports=no
301 |
302 | # Minimum lines number of a similarity.
303 | min-similarity-lines=4
304 |
305 |
306 | [VARIABLES]
307 |
308 | # List of additional names supposed to be defined in builtins. Remember that
309 | # you should avoid to define new builtins when possible.
310 | additional-builtins=
311 |
312 | # Tells whether unused global variables should be treated as a violation.
313 | allow-global-unused-variables=yes
314 |
315 | # List of strings which can identify a callback function by name. A callback
316 | # name must start or end with one of those strings.
317 | callbacks=cb_,
318 | _cb
319 |
320 | # A regular expression matching the name of dummy variables (i.e. expectedly
321 | # not used).
322 | dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
323 |
324 | # Argument names that match this expression will be ignored. Default to name
325 | # with leading underscore
326 | ignored-argument-names=_.*|^ignored_|^unused_
327 |
328 | # Tells whether we should check for unused import in __init__ files.
329 | init-import=no
330 |
331 | # List of qualified module names which can have objects that can redefine
332 | # builtins.
333 | redefining-builtins-modules=six.moves,past.builtins,future.builtins
334 |
335 |
336 | [BASIC]
337 |
338 | # Naming style matching correct argument names
339 | argument-naming-style=snake_case
340 |
341 | # Regular expression matching correct argument names. Overrides argument-
342 | # naming-style
343 | #argument-rgx=
344 |
345 | # Naming style matching correct attribute names
346 | attr-naming-style=snake_case
347 |
348 | # Regular expression matching correct attribute names. Overrides attr-naming-
349 | # style
350 | #attr-rgx=
351 |
352 | # Bad variable names which should always be refused, separated by a comma
353 | bad-names=foo,
354 | bar,
355 | baz,
356 | toto,
357 | tutu,
358 | tata
359 |
360 | # Naming style matching correct class attribute names
361 | class-attribute-naming-style=any
362 |
363 | # Regular expression matching correct class attribute names. Overrides class-
364 | # attribute-naming-style
365 | #class-attribute-rgx=
366 |
367 | # Naming style matching correct class names
368 | class-naming-style=PascalCase
369 |
370 | # Regular expression matching correct class names. Overrides class-naming-style
371 | #class-rgx=
372 |
373 | # Naming style matching correct constant names
374 | const-naming-style=UPPER_CASE
375 |
376 | # Regular expression matching correct constant names. Overrides const-naming-
377 | # style
378 | #const-rgx=
379 |
380 | # Minimum line length for functions/classes that require docstrings, shorter
381 | # ones are exempt.
382 | docstring-min-length=-1
383 |
384 | # Naming style matching correct function names
385 | function-naming-style=snake_case
386 |
387 | # Regular expression matching correct function names. Overrides function-
388 | # naming-style
389 | #function-rgx=
390 |
391 | # Good variable names which should always be accepted, separated by a comma
392 | good-names=i,
393 | j,
394 | k,
395 | ex,
396 | Run,
397 | _
398 |
399 | # Include a hint for the correct naming format with invalid-name
400 | include-naming-hint=no
401 |
402 | # Naming style matching correct inline iteration names
403 | inlinevar-naming-style=any
404 |
405 | # Regular expression matching correct inline iteration names. Overrides
406 | # inlinevar-naming-style
407 | #inlinevar-rgx=
408 |
409 | # Naming style matching correct method names
410 | method-naming-style=snake_case
411 |
412 | # Regular expression matching correct method names. Overrides method-naming-
413 | # style
414 | #method-rgx=
415 |
416 | # Naming style matching correct module names
417 | module-naming-style=snake_case
418 |
419 | # Regular expression matching correct module names. Overrides module-naming-
420 | # style
421 | #module-rgx=
422 |
423 | # Colon-delimited sets of names that determine each other's naming style when
424 | # the name regexes allow several styles.
425 | name-group=
426 |
427 | # Regular expression which should only match function or class names that do
428 | # not require a docstring.
429 | no-docstring-rgx=^_
430 |
431 | # List of decorators that produce properties, such as abc.abstractproperty. Add
432 | # to this list to register other decorators that produce valid properties.
433 | property-classes=abc.abstractproperty
434 |
435 | # Naming style matching correct variable names
436 | variable-naming-style=snake_case
437 |
438 | # Regular expression matching correct variable names. Overrides variable-
439 | # naming-style
440 | #variable-rgx=
441 |
442 |
443 | [MISCELLANEOUS]
444 |
445 | # List of note tags to take in consideration, separated by a comma.
446 | notes=FIXME,
447 | XXX,
448 | TODO
449 |
450 |
451 | [IMPORTS]
452 |
453 | # Allow wildcard imports from modules that define __all__.
454 | allow-wildcard-with-all=no
455 |
456 | # Analyse import fallback blocks. This can be used to support both Python 2 and
457 | # 3 compatible code, which means that the block might have code that exists
458 | # only in one or another interpreter, leading to false positives when analysed.
459 | analyse-fallback-blocks=no
460 |
461 | # Deprecated modules which should not be used, separated by a comma
462 | deprecated-modules=regsub,
463 | TERMIOS,
464 | Bastion,
465 | rexec
466 |
467 | # Create a graph of external dependencies in the given file (report RP0402 must
468 | # not be disabled)
469 | ext-import-graph=
470 |
471 | # Create a graph of every (i.e. internal and external) dependencies in the
472 | # given file (report RP0402 must not be disabled)
473 | import-graph=
474 |
475 | # Create a graph of internal dependencies in the given file (report RP0402 must
476 | # not be disabled)
477 | int-import-graph=
478 |
479 | # Force import order to recognize a module as part of the standard
480 | # compatibility libraries.
481 | known-standard-library=
482 |
483 | # Force import order to recognize a module as part of a third party library.
484 | known-third-party=enchant
485 |
486 |
487 | [DESIGN]
488 |
489 | # Maximum number of arguments for function / method
490 | max-args=5
491 |
492 | # Maximum number of attributes for a class (see R0902).
493 | max-attributes=7
494 |
495 | # Maximum number of boolean expressions in a if statement
496 | max-bool-expr=5
497 |
498 | # Maximum number of branch for function / method body
499 | max-branches=12
500 |
501 | # Maximum number of locals for function / method body
502 | max-locals=15
503 |
504 | # Maximum number of parents for a class (see R0901).
505 | max-parents=7
506 |
507 | # Maximum number of public methods for a class (see R0904).
508 | max-public-methods=20
509 |
510 | # Maximum number of return / yield for function / method body
511 | max-returns=6
512 |
513 | # Maximum number of statements in function / method body
514 | max-statements=50
515 |
516 | # Minimum number of public methods for a class (see R0903).
517 | min-public-methods=2
518 |
519 |
520 | [CLASSES]
521 |
522 | # List of method names used to declare (i.e. assign) instance attributes.
523 | defining-attr-methods=__init__,
524 | __new__,
525 | setUp
526 |
527 | # List of member names, which should be excluded from the protected access
528 | # warning.
529 | exclude-protected=_asdict,
530 | _fields,
531 | _replace,
532 | _source,
533 | _make
534 |
535 | # List of valid names for the first argument in a class method.
536 | valid-classmethod-first-arg=cls
537 |
538 | # List of valid names for the first argument in a metaclass class method.
539 | valid-metaclass-classmethod-first-arg=mcs
540 |
541 |
542 | [EXCEPTIONS]
543 |
544 | # Exceptions that will emit a warning when being caught. Defaults to
545 | # "Exception"
546 | overgeneral-exceptions=Exception
547 |
--------------------------------------------------------------------------------
/pytest_extra_requirements.txt:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: MIT
2 |
3 | # Write extra requirements for running pytest here:
4 | # If you need ansible then uncomment the following line:
5 | #-ransible_pytest_extra_requirements.txt
6 | # If you need mock then uncomment the following line:
7 | #mock ; python_version < "3.0"
8 |
--------------------------------------------------------------------------------
/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Set version specific variables
3 | include_tasks: tasks/set_vars.yml
4 |
5 | - name: Populate service facts
6 | service_facts:
7 |
8 | - name: Set variable `timesync_services` with filtered uniq service names
9 | set_fact:
10 | timesync_services: "{{ ansible_facts.services.values() |
11 | selectattr('name', 'defined') |
12 | selectattr('status', 'defined') |
13 | rejectattr('status', 'match', '^not-found$') |
14 | rejectattr('status', 'match', '^masked$') |
15 | rejectattr('status', 'match', '^failed$') |
16 | map(attribute='name') |
17 | map('regex_replace', '[.]service.*$', '') |
18 | map('regex_replace', '@$', '') |
19 | unique |
20 | list }}"
21 |
22 | - name: Check that variable 'timesync_services' is defined
23 | assert:
24 | that: timesync_services is defined
25 | fail_msg: "Variable 'timesync_services' is not defined"
26 |
27 | - name: Check if only NTP is needed
28 | set_fact:
29 | timesync_mode: 1
30 | when: timesync_ptp_domains | length == 0
31 |
32 | - name: Check if single PTP is needed
33 | set_fact:
34 | timesync_mode: 2
35 | when:
36 | - timesync_mode is not defined
37 | - timesync_ntp_servers | length == 0
38 | - timesync_ptp_domains | length == 1
39 | - timesync_ptp_domains[0].interfaces | length == 1
40 |
41 | - name: Check if both NTP and PTP are needed
42 | set_fact:
43 | timesync_mode: 3
44 | when: timesync_mode is not defined
45 |
46 | - name: Determine current NTP provider
47 | timesync_provider: # noqa fqcn[action]
48 | when:
49 | - timesync_mode != 2
50 | - timesync_ntp_provider | length == 0
51 |
52 | - name: Select NTP provider
53 | set_fact:
54 | timesync_ntp_provider: "{{
55 | timesync_ntp_provider_current |
56 | default(timesync_ntp_provider_os_default, true) }}"
57 | when:
58 | - timesync_mode != 2
59 | - timesync_ntp_provider | length == 0
60 |
61 | - name: Install chrony
62 | package:
63 | name: chrony
64 | state: present
65 | use: "{{ (__timesync_is_ostree | d(false)) |
66 | ternary('ansible.posix.rhel_rpm_ostree', omit) }}"
67 | when:
68 | - timesync_mode != 2
69 | - timesync_ntp_provider == 'chrony'
70 | register: timesync_chrony_result
71 |
72 | - name: Install ntp
73 | package:
74 | name: ntp
75 | state: present
76 | use: "{{ (__timesync_is_ostree | d(false)) |
77 | ternary('ansible.posix.rhel_rpm_ostree', omit) }}"
78 | when:
79 | - timesync_mode != 2
80 | - timesync_ntp_provider == 'ntp'
81 | register: timesync_ntp_result
82 |
83 | - name: Install linuxptp
84 | package:
85 | name: linuxptp
86 | state: present
87 | use: "{{ (__timesync_is_ostree | d(false)) |
88 | ternary('ansible.posix.rhel_rpm_ostree', omit) }}"
89 | when: timesync_mode != 1
90 | register: timesync_linuxptp_result
91 |
92 | - name: Handle reboot for transactional update systems
93 | when:
94 | - __timesync_is_transactional | d(false)
95 | - timesync_chrony_result is changed or
96 | timesync_ntp_result is changed or
97 | timesync_linuxptp_result is changed
98 | block:
99 | - name: Notify user that reboot is needed to apply changes
100 | debug:
101 | msg: >
102 | Reboot required to apply changes due to transactional updates.
103 |
104 | - name: Reboot transactional update systems
105 | reboot:
106 | msg: Rebooting the system to apply transactional update changes.
107 | when: timesync_transactional_update_reboot_ok | bool
108 |
109 | - name: Fail if reboot is needed and not set
110 | fail:
111 | msg: >
112 | Reboot is required but not allowed. Please set
113 | 'timesync_transactional_update_reboot_ok' to proceed.
114 | when:
115 | - timesync_transactional_update_reboot_ok is none
116 |
117 | - name: Gather package facts
118 | package_facts:
119 | manager: auto
120 |
121 | - name: Run phc_ctl on PTP interface
122 | command: phc_ctl -q {{ timesync_ptp_domains[0].interfaces[0] }}
123 | register: timesync_phc_ctl_output
124 | changed_when: false
125 | check_mode: false
126 | when: timesync_mode == 2
127 | ignore_errors: true
128 |
129 | - name: Check if PTP interface supports HW timestamping
130 | set_fact:
131 | timesync_mode2_hwts: "{{ timesync_phc_ctl_output.rc == 0 }}"
132 | when: timesync_mode == 2
133 |
134 | - name: Generate chrony.conf file
135 | template:
136 | src: chrony.conf.j2
137 | dest: "{{ timesync_chrony_conf_path }}"
138 | backup: true
139 | mode: "0644"
140 | # wokeignore:rule=master
141 | notify: Restart {{ 'chronyd' if timesync_mode == 1 else 'timemaster' }}
142 | when:
143 | - timesync_mode != 2
144 | - timesync_ntp_provider == 'chrony'
145 | - "'chrony' in ansible_facts.packages"
146 |
147 | - name: Generate chronyd sysconfig file
148 | template:
149 | src: chronyd.sysconfig.j2
150 | dest: "{{ timesync_chrony_sysconfig_path }}"
151 | backup: true
152 | mode: "0644"
153 | notify: Restart chronyd
154 | when:
155 | - timesync_mode == 1
156 | - timesync_ntp_provider == 'chrony'
157 | - "'chrony' in ansible_facts.packages"
158 |
159 | - name: Generate ntp.conf file
160 | template:
161 | src: ntp.conf.j2
162 | dest: /etc/ntp.conf
163 | backup: true
164 | mode: "0644"
165 | # wokeignore:rule=master
166 | notify: Restart {{ 'ntpd' if timesync_mode == 1 else 'timemaster' }}
167 | when:
168 | - timesync_mode != 2
169 | - timesync_ntp_provider == 'ntp'
170 | - "'ntp' in ansible_facts.packages"
171 |
172 | - name: Generate ntpd sysconfig file
173 | template:
174 | src: ntpd.sysconfig.j2
175 | dest: "{{ timesync_ntp_sysconfig_path }}"
176 | backup: true
177 | mode: "0644"
178 | notify: Restart ntpd
179 | when:
180 | - timesync_mode == 1
181 | - timesync_ntp_provider == 'ntp'
182 | - "'ntp' in ansible_facts.packages"
183 |
184 | - name: Generate ptp4l.conf file
185 | template:
186 | src: ptp4l.conf.j2
187 | dest: /etc/ptp4l.conf
188 | backup: true
189 | mode: "0644"
190 | notify: Restart ptp4l
191 | when:
192 | - timesync_mode == 2
193 | - "'linuxptp' in ansible_facts.packages"
194 |
195 | - name: Generate ptp4l sysconfig file
196 | template:
197 | src: ptp4l.sysconfig.j2
198 | dest: "{{ timesync_ptp4l_sysconfig_path }}"
199 | backup: true
200 | mode: "0644"
201 | notify: Restart ptp4l
202 | when:
203 | - timesync_mode == 2
204 | - "'linuxptp' in ansible_facts.packages"
205 | - timesync_ptp4l_sysconfig_path | length > 0
206 |
207 | - name: Generate phc2sys sysconfig file
208 | template:
209 | src: phc2sys.sysconfig.j2
210 | dest: /etc/sysconfig/phc2sys
211 | backup: true
212 | mode: "0644"
213 | notify: Restart phc2sys
214 | when:
215 | - timesync_mode == 2
216 | - timesync_mode2_hwts
217 | - "'linuxptp' in ansible_facts.packages"
218 | - timesync_phc2sys_sysconfig_path | length > 0
219 |
220 | # wokeignore:rule=master
221 | - name: Generate timemaster.conf file
222 | template:
223 | # wokeignore:rule=master
224 | src: timemaster.conf.j2
225 | # wokeignore:rule=master
226 | dest: "{{ timesync_timemaster_config_path }}"
227 | backup: true
228 | mode: "0644"
229 | # wokeignore:rule=master
230 | notify: Restart timemaster
231 | when:
232 | - timesync_mode == 3
233 | - "'linuxptp' in ansible_facts.packages"
234 |
235 | - name: Update network sysconfig file
236 | lineinfile:
237 | dest: /etc/sysconfig/network
238 | create: true
239 | backup: true
240 | mode: "0644"
241 | regexp: '^PEERNTP='
242 | line: 'PEERNTP=no'
243 | # yamllint disable-line rule:line-length
244 | state: "{{ 'absent' if timesync_dhcp_ntp_servers else 'present' }}" # noqa args[module]
245 | notify: Restart {{ timesync_ntp_provider + 'd' }}
246 | when:
247 | - timesync_mode == 1
248 | - ansible_facts['os_family'] == 'RedHat'
249 |
250 | - name: Disable chronyd
251 | service:
252 | name: chronyd
253 | state: stopped
254 | enabled: false
255 | when:
256 | - timesync_mode != 1 or timesync_ntp_provider != 'chrony'
257 | - "'chronyd' in timesync_services"
258 | register: __disable_result
259 | failed_when:
260 | - __disable_result is failed
261 | - not __disable_result.msg is match(
262 | 'Could not find the requested service chronyd:')
263 |
264 | - name: Disable ntpd
265 | service:
266 | name: ntpd
267 | state: stopped
268 | enabled: false
269 | when:
270 | - timesync_mode != 1 or timesync_ntp_provider != 'ntp'
271 | - "'ntpd' in timesync_services"
272 | register: __disable_result
273 | failed_when:
274 | - __disable_result is failed
275 | - not __disable_result.msg is match(
276 | 'Could not find the requested service ntpd:')
277 |
278 | - name: Disable ntpdate
279 | service:
280 | name: ntpdate
281 | state: stopped
282 | enabled: false
283 | when: "'ntpdate' in timesync_services"
284 | register: __disable_result
285 | failed_when:
286 | - __disable_result is failed
287 | - not __disable_result.msg is match(
288 | 'Could not find the requested service ntpdate:')
289 |
290 | - name: Disable sntp
291 | service:
292 | name: sntp
293 | state: stopped
294 | enabled: false
295 | when: "'sntp' in timesync_services"
296 | register: __disable_result
297 | failed_when:
298 | - __disable_result is failed
299 | - not __disable_result.msg is match(
300 | 'Could not find the requested service sntp:')
301 |
302 | - name: Disable ptp4l
303 | service:
304 | name: ptp4l
305 | state: stopped
306 | enabled: false
307 | when:
308 | - timesync_mode != 2
309 | - "'ptp4l' in timesync_services"
310 | register: __disable_result
311 | failed_when:
312 | - __disable_result is failed
313 | - not __disable_result.msg is match(
314 | 'Could not find the requested service ptp4l:')
315 |
316 | - name: Disable phc2sys
317 | service:
318 | name: phc2sys
319 | state: stopped
320 | enabled: false
321 | when:
322 | - timesync_mode != 2 or not timesync_mode2_hwts
323 | - "'phc2sys' in timesync_services"
324 | register: __disable_result
325 | failed_when:
326 | - __disable_result is failed
327 | - not __disable_result.msg is match(
328 | 'Could not find the requested service phc2sys:')
329 |
330 | # wokeignore:rule=master
331 | - name: Disable timemaster
332 | vars:
333 | # wokeignore:rule=master
334 | __timemstr: timemaster
335 | service:
336 | name: "{{ __timemstr }}"
337 | state: stopped
338 | enabled: false
339 | when:
340 | - timesync_mode != 3
341 | - __timemstr in timesync_services
342 | register: __disable_result
343 | failed_when:
344 | - __disable_result is failed
345 | - not __disable_result.msg is match(
346 | 'Could not find the requested service ' ~ __timemstr ~ ':')
347 |
348 | - name: Enable chronyd
349 | service:
350 | name: chronyd
351 | state: started
352 | enabled: true
353 | when:
354 | - timesync_mode == 1
355 | - timesync_ntp_provider == 'chrony'
356 |
357 | - name: Enable ntpd
358 | service:
359 | name: ntpd
360 | state: started
361 | enabled: true
362 | when:
363 | - timesync_mode == 1
364 | - timesync_ntp_provider == 'ntp'
365 |
366 | - name: Enable ptp4l
367 | service:
368 | name: ptp4l
369 | state: started
370 | enabled: true
371 | when: timesync_mode == 2
372 |
373 | - name: Enable phc2sys
374 | service:
375 | name: phc2sys
376 | state: started
377 | enabled: true
378 | when:
379 | - timesync_mode == 2
380 | - timesync_mode2_hwts
381 |
382 | # wokeignore:rule=master
383 | - name: Enable timemaster
384 | service:
385 | # wokeignore:rule=master
386 | name: timemaster
387 | state: started
388 | enabled: true
389 | when: timesync_mode == 3
390 |
--------------------------------------------------------------------------------
/tasks/set_vars.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Ensure ansible_facts used by role
3 | setup:
4 | gather_subset: "{{ __timesync_required_facts_subsets }}"
5 | when: __timesync_required_facts |
6 | difference(ansible_facts.keys() | list) | length > 0
7 |
8 | - name: Determine if system is ostree and set flag
9 | when: not __timesync_is_ostree is defined
10 | block:
11 | - name: Check if system is ostree
12 | stat:
13 | path: /run/ostree-booted
14 | register: __ostree_booted_stat
15 |
16 | - name: Set flag to indicate system is ostree
17 | set_fact:
18 | __timesync_is_ostree: "{{ __ostree_booted_stat.stat.exists }}"
19 |
20 | - name: Determine if system is transactional update and set flag
21 | when: not __timesync_is_transactional is defined
22 | block:
23 | - name: Check if transactional-update exists in /sbin
24 | stat:
25 | path: /sbin/transactional-update
26 | register: __transactional_update_stat
27 |
28 | - name: Set flag if transactional-update exists
29 | set_fact:
30 | __timesync_is_transactional: "{{ __transactional_update_stat.stat.exists }}"
31 |
32 | - name: Set platform/version specific variables
33 | include_vars: "{{ lookup('first_found', ffparams) }}"
34 | vars:
35 | ffparams:
36 | files:
37 | - "{{ ansible_facts['distribution'] }}_\
38 | {{ ansible_facts['distribution_version'] }}.yml"
39 | - "{{ ansible_facts['distribution'] }}_\
40 | {{ ansible_facts['distribution_major_version'] }}.yml"
41 | - "{{ ansible_facts['distribution'] }}.yml"
42 | - "{{ ansible_facts['os_family'] }}.yml"
43 | - "default.yml"
44 | paths:
45 | - "{{ role_path }}/vars"
46 |
--------------------------------------------------------------------------------
/templates/chrony.conf.j2:
--------------------------------------------------------------------------------
1 | {{ ansible_managed | comment }}
2 | {{ "system_role:timesync" | comment(prefix="", postfix="") }}
3 |
4 | {% for value in timesync_ntp_servers %}
5 | {{ 'pool' if 'pool' in value and value['pool'] else 'server' }} {{
6 | value['hostname'] }}{{
7 | ' minpoll {0}'.format(value['minpoll']) if 'minpoll' in value else '' }}{{
8 | ' maxpoll {0}'.format(value['maxpoll']) if 'maxpoll' in value else '' }}{{
9 | ' nts' if 'nts' in value and value['nts'] else '' }}{{
10 | ' iburst' if 'iburst' in value and value['iburst'] else '' }}{{
11 | ' prefer' if 'prefer' in value and value['prefer'] else '' }}{{
12 | ' trust' if 'trust' in value and value['trust'] else '' }}{{
13 | ' xleave' if __timesync_chrony_version is version('3.0', '>=') and
14 | 'xleave' in value and value['xleave'] else '' }}{{
15 | ' filter {0}'.format(value['filter'])
16 | if __timesync_chrony_version is version('3.4', '>=') and
17 | 'filter' in value and value['filter'] > 1 else '' }}
18 | {% endfor %}
19 |
20 | {% if timesync_dhcp_ntp_servers and timesync_chrony_dhcp_sourcedir %}
21 | # Use NTP servers from DHCP.
22 | sourcedir {{ timesync_chrony_dhcp_sourcedir }}
23 |
24 | {% endif %}
25 | {% if timesync_step_threshold | float != 0.0 %}
26 | # Allow the system clock to be stepped in the first three updates.
27 | makestep {{ timesync_step_threshold if timesync_step_threshold | float > 0.0 else '1.0' }} 3
28 |
29 | {% endif %}
30 | # Enable kernel synchronization of the real-time clock (RTC).
31 | rtcsync
32 |
33 | {% if __timesync_chrony_version is version('3.0', '>=') and
34 | timesync_ntp_hwts_interfaces|length > 0 %}
35 | # Enable hardware timestamping.
36 | {% for interface in timesync_ntp_hwts_interfaces %}
37 | hwtimestamp {{ interface }}{% if __timesync_chrony_version is version('3.1', '>=') %}
38 | minpoll {{ (timesync_ntp_servers | rejectattr('minpoll', 'undefined') |
39 | map(attribute='minpoll') | list + [0]) | min }}{% endif %}
40 |
41 | {% endfor %}
42 |
43 | {% endif %}
44 | {% if timesync_min_sources | int > 1 %}
45 | # Increase the minimum number of selectable sources required to adjust
46 | # the system clock.
47 | minsources {{ timesync_min_sources }}
48 |
49 | {% endif %}
50 | # Record the rate at which the system clock gains/losses time.
51 | driftfile /var/lib/chrony/drift
52 |
53 | {% if __timesync_chrony_version is version('2.0', '<') %}
54 | # Decrease weight of stratum in source selection.
55 | stratumweight 0.001
56 |
57 | # Listen for commands only on localhost.
58 | bindcmdaddress 127.0.0.1
59 | bindcmdaddress ::1
60 |
61 | {% endif %}
62 | {% if __timesync_chrony_version is version('2.2', '<') %}
63 | # Specify file containing keys for NTP and command authentication.
64 | keyfile /etc/chrony.keys
65 |
66 | # Specify ID of command key.
67 | commandkey 1
68 |
69 | # Generate command key if missing.
70 | generatecommandkey
71 |
72 | {% endif %}
73 | {% if __timesync_chrony_version is version('4.0', '>=') %}
74 | # Save NTS keys and cookies.
75 | ntsdumpdir /var/lib/chrony
76 |
77 | {% endif %}
78 | {% if timesync_max_distance | int != 0 %}
79 | # Limit maximum root distance.
80 | maxdistance {{ timesync_max_distance }}
81 |
82 | {% endif %}
83 | {% if timesync_chrony_custom_settings | default([]) | length > 0 %}
84 | # Custom settings
85 | {% for custom_setting in timesync_chrony_custom_settings %}
86 | {{ custom_setting }}
87 | {% endfor %}
88 | {% endif %}
89 |
--------------------------------------------------------------------------------
/templates/chronyd.sysconfig.j2:
--------------------------------------------------------------------------------
1 | {{ ansible_managed | comment }}
2 | {{ "system_role:timesync" | comment(prefix="", postfix="") }}
3 |
4 | OPTIONS="{{ timesync_chrony_sysconfig_options }}{{ ' -4' if timesync_ntp_ip_family == 'IPv4'
5 | else ' -6' if timesync_ntp_ip_family == 'IPv6' else '' }}"
6 |
--------------------------------------------------------------------------------
/templates/ntp.conf.j2:
--------------------------------------------------------------------------------
1 | {{ ansible_managed | comment }}
2 | {{ "system_role:timesync" | comment(prefix="", postfix="") }}
3 |
4 | {% for value in timesync_ntp_servers %}
5 | {{ 'pool' if 'pool' in value and value['pool'] else 'server' }} {{
6 | value['hostname'] }}{{
7 | ' minpoll {0}'.format(value['minpoll']) if 'minpoll' in value else '' }}{{
8 | ' maxpoll {0}'.format(value['maxpoll']) if 'maxpoll' in value else '' }}{{
9 | ' iburst' if 'iburst' in value and value['iburst'] else '' }}{{
10 | ' prefer' if 'prefer' in value and value['prefer'] else '' }}{{
11 | ' true' if 'trust' in value and value['trust'] else '' }}
12 | {% if 'nts' in value and value['nts'] %}
13 | # Disable clock control due to missing NTS support.
14 | disable ntp
15 | {% endif %}
16 | {% endfor %}
17 |
18 | driftfile /var/lib/ntp/drift
19 |
20 | # Permit time synchronization with our time source, but do not
21 | # permit the source to query or modify the service on this system.
22 | restrict default nomodify notrap nopeer noquery
23 | {% if __timesync_ntp_version is version('4.2.6', '<') %}
24 | restrict -6 default nomodify notrap nopeer noquery
25 | {% endif %}
26 |
27 | # Permit all access over the loopback interface. This could
28 | # be tightened as well, but to do so would effect some of
29 | # the administrative functions.
30 | restrict 127.0.0.1
31 | restrict ::1
32 |
33 | {% if timesync_step_threshold | float >= 0.0 %}
34 | # Specify the step threshold.
35 | tinker step {{ timesync_step_threshold }}
36 |
37 | {% endif %}
38 | {% if timesync_min_sources | int > 1 %}
39 | # Increase the minimum number of selectable sources required to adjust
40 | # the system clock.
41 | tos minsane {{ timesync_min_sources }}
42 |
43 | {% endif %}
44 | {% if timesync_max_distance | int != 0 %}
45 | # Limit maximum root distance.
46 | tos maxdist {{ timesync_max_distance }}
47 |
48 | {% endif %}
49 |
--------------------------------------------------------------------------------
/templates/ntpd.sysconfig.j2:
--------------------------------------------------------------------------------
1 | {{ ansible_managed | comment }}
2 | {{ "system_role:timesync" | comment(prefix="", postfix="") }}
3 |
4 | OPTIONS="-g{{ ' -u ntp:ntp -p /var/run/ntpd.pid' if ansible_distribution in ['OracleLinux', 'RedHat', 'CentOS'] and ansible_distribution_major_version | int < 7 else '' }}{{
5 | ' -4' if timesync_ntp_ip_family == 'IPv4'
6 | else ' -6' if timesync_ntp_ip_family == 'IPv6'
7 | else '' }}"
8 |
--------------------------------------------------------------------------------
/templates/phc2sys.sysconfig.j2:
--------------------------------------------------------------------------------
1 | {{ ansible_managed | comment }}
2 | {{ "system_role:timesync" | comment(prefix="", postfix="") }}
3 |
4 | OPTIONS="-a -r{{ ' -F ' ~ timesync_step_threshold if timesync_step_threshold | float >= 0.0 else '' }}"
5 |
--------------------------------------------------------------------------------
/templates/ptp4l.conf.j2:
--------------------------------------------------------------------------------
1 | {{ ansible_managed | comment }}
2 | {{ "system_role:timesync" | comment(prefix="", postfix="") }}
3 |
4 | [global]
5 | {# wokeignore:rule=slave #}
6 | slaveOnly 1
7 | domainNumber {{ timesync_ptp_domains[0].number }}
8 | time_stamping {{ 'hardware' if timesync_mode2_hwts else 'software' }}
9 | {% if 'transport' in timesync_ptp_domains[0] %}
10 | network_transport {{ timesync_ptp_domains[0]['transport'] }}
11 | {% endif %}
12 | {% if 'udp_ttl' in timesync_ptp_domains[0] %}
13 | udp_ttl {{ timesync_ptp_domains[0]['udp_ttl'] }}
14 | {% endif %}
15 | {% if 'hybrid_e2e' in timesync_ptp_domains[0] and timesync_ptp_domains[0]['hybrid_e2e'] %}
16 | hybrid_e2e 1
17 | {% endif %}
18 | {% if not timesync_mode2_hwts and timesync_step_threshold | float >= 0.0 %}
19 | first_step_threshold {{ timesync_step_threshold }}
20 | {% endif %}
21 |
--------------------------------------------------------------------------------
/templates/ptp4l.sysconfig.j2:
--------------------------------------------------------------------------------
1 | {{ ansible_managed | comment }}
2 | {{ "system_role:timesync" | comment(prefix="", postfix="") }}
3 |
4 | OPTIONS="-f /etc/ptp4l.conf -i {{ timesync_ptp_domains[0].interfaces[0] }}"
5 |
--------------------------------------------------------------------------------
/templates/timemaster.conf.j2:
--------------------------------------------------------------------------------
1 | {{ ansible_managed | comment }}
2 | {{ "system_role:timesync" | comment(prefix="", postfix="") }}
3 |
4 | {% for value in timesync_ptp_domains %}
5 | [ptp_domain {{ value['number'] }}]
6 | interfaces {{ value['interfaces']|join(' ') }}
7 | {% if 'delay' in value %}
8 | delay {{ value['delay'] }}
9 | {% endif %}
10 | {% if 'transport' in value %}
11 | ptp4l_option network_transport {{ value['transport'] }}
12 | {% endif %}
13 | {% if 'udp_ttl' in value %}
14 | ptp4l_option udp_ttl {{ value['udp_ttl'] }}
15 | {% endif %}
16 | {% if 'hybrid_e2e' in value and value['hybrid_e2e'] %}
17 | ptp4l_option hybrid_e2e 1
18 | {% endif %}
19 |
20 | {% endfor %}
21 | {# wokeignore:rule=master #}
22 | [timemaster]
23 | ntp_program {{ 'ntpd' if timesync_ntp_provider == 'ntp' else 'chronyd' }}
24 |
25 | [chrony.conf]
26 | include /etc/chrony.conf
27 |
28 | [ntp.conf]
29 | includefile /etc/ntp.conf
30 |
31 | [ptp4l.conf]
32 |
33 | [chronyd]
34 | path /usr/sbin/chronyd
35 | {% if timesync_ntp_provider == 'chrony' and __timesync_chrony_version is version('1.30', '<') %}
36 | options -u chrony
37 | {% endif %}
38 |
39 | [ntpd]
40 | path /usr/sbin/ntpd
41 | options -u ntp:ntp -g
42 |
43 | [phc2sys]
44 | path /usr/sbin/phc2sys
45 | options -l 6
46 |
47 | [ptp4l]
48 | path /usr/sbin/ptp4l
49 | options -l 6
50 |
--------------------------------------------------------------------------------
/tests/.fmf/version:
--------------------------------------------------------------------------------
1 | 1
2 |
--------------------------------------------------------------------------------
/tests/inventory.yaml.j2:
--------------------------------------------------------------------------------
1 | all:
2 | hosts:
3 | {{ inventory_hostname }}:
4 | {% for key in ["ansible_all_ipv4_addresses", "ansible_all_ipv6_addresses",
5 | "ansible_default_ipv4", "ansible_default_ipv6", "ansible_host",
6 | "ansible_port", "ansible_ssh_common_args",
7 | "ansible_ssh_private_key_file","ansible_user"] %}
8 | {% if key in hostvars[inventory_hostname] %}
9 | {{ key }}: {{ hostvars[inventory_hostname][key] }}
10 | {% endif %}
11 | {% endfor %}
12 |
--------------------------------------------------------------------------------
/tests/provision.fmf:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | standard-inventory-qcow2:
4 | qemu:
5 | net_nic:
6 | # Use qemu-system-x86_64 -net nic,model=help for a list of available devices.
7 | model: e1000
8 |
--------------------------------------------------------------------------------
/tests/roles/linux-system-roles.timesync/defaults:
--------------------------------------------------------------------------------
1 | ../../../defaults
--------------------------------------------------------------------------------
/tests/roles/linux-system-roles.timesync/handlers:
--------------------------------------------------------------------------------
1 | ../../../handlers
--------------------------------------------------------------------------------
/tests/roles/linux-system-roles.timesync/library:
--------------------------------------------------------------------------------
1 | ../../../library
--------------------------------------------------------------------------------
/tests/roles/linux-system-roles.timesync/meta:
--------------------------------------------------------------------------------
1 | ../../../meta
--------------------------------------------------------------------------------
/tests/roles/linux-system-roles.timesync/tasks:
--------------------------------------------------------------------------------
1 | ../../../tasks
--------------------------------------------------------------------------------
/tests/roles/linux-system-roles.timesync/templates:
--------------------------------------------------------------------------------
1 | ../../../templates
--------------------------------------------------------------------------------
/tests/roles/linux-system-roles.timesync/vars:
--------------------------------------------------------------------------------
1 | ../../../vars
--------------------------------------------------------------------------------
/tests/setup-snapshot.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Setup snapshot
3 | hosts: all
4 | tasks:
5 | - name: Set platform/version specific variables
6 | include_role:
7 | name: linux-system-roles.timesync
8 | tasks_from: set_vars.yml
9 | public: true
10 |
11 | - name: Install test packages to put them in the local cache
12 | package:
13 | name:
14 | - chrony
15 | - ntp
16 | - linuxptp
17 | state: present
18 | no_log: true
19 | ignore_errors: true # noqa ignore-errors
20 |
21 | - name: Uninstall test packages
22 | package:
23 | name:
24 | - chrony
25 | - ntp
26 | - linuxptp
27 | state: absent
28 | no_log: true
29 |
--------------------------------------------------------------------------------
/tests/tasks/check_header.yml:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: MIT
2 | ---
3 | - name: Get file
4 | slurp:
5 | path: "{{ __file }}"
6 | register: __content
7 | when: not __file_content is defined
8 |
9 | - name: Check for presence of ansible managed header, fingerprint
10 | assert:
11 | that:
12 | - __ansible_managed in content
13 | - __fingerprint in content
14 | vars:
15 | content: "{{ (__file_content | d(__content)).content | b64decode }}"
16 | __ansible_managed: "{{ lookup('template', 'get_ansible_managed.j2') }}"
17 |
--------------------------------------------------------------------------------
/tests/tasks/cleanup.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Reset settings and provider to os default
3 | include_role:
4 | name: linux-system-roles.timesync
5 | vars:
6 | timesync_ntp_provider: "{{ timesync_ntp_provider_os_default }}"
7 | timesync_ptp_domains: []
8 | timesync_ntp_servers: []
9 |
--------------------------------------------------------------------------------
/tests/tasks/setup.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # common test setup tasks
3 | - name: Determine if system is ostree and set flag
4 | when: not __timesync_is_ostree is defined
5 | block:
6 | - name: Check if system is ostree
7 | stat:
8 | path: /run/ostree-booted
9 | register: __ostree_booted_stat
10 |
11 | - name: Set flag to indicate system is ostree
12 | set_fact:
13 | __timesync_is_ostree: "{{ __ostree_booted_stat.stat.exists }}"
14 |
15 | - name: Ensure iproute for gathering default_ipv4 fact
16 | package:
17 | name: iproute # for fact gathering for ip facts
18 | state: present
19 | use: "{{ (__timesync_is_ostree | d(false)) |
20 | ternary('ansible.posix.rhel_rpm_ostree', omit) }}"
21 |
22 | - name: Ensure ansible_facts used by test
23 | setup:
24 | gather_subset: "{{ __required_facts_subsets }}"
25 | when: __required_facts |
26 | difference(ansible_facts.keys() | list) | length > 0
27 | vars:
28 | __required_facts:
29 | - default_ipv4
30 | - distribution
31 | - distribution_major_version
32 | - distribution_version
33 | - os_family
34 | __required_facts_subsets: "{{ ['!all', '!min'] + __required_facts }}"
35 |
36 | - name: Debug
37 | debug:
38 | msg: facts {{ ansible_facts | to_nice_json }}
39 |
40 | - name: Skip test on ostree systems if unsupported
41 | meta: end_host
42 | when:
43 | - __timesync_ostree_unsupported | d(false)
44 | - __timesync_is_ostree | d(false)
45 |
--------------------------------------------------------------------------------
/tests/templates/get_ansible_managed.j2:
--------------------------------------------------------------------------------
1 | {{ ansible_managed | comment(__comment_type | d("plain")) }}
2 |
--------------------------------------------------------------------------------
/tests/tests_chrony.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Configure time synchronization with NTP servers
3 | hosts: all
4 | vars:
5 | timesync_chrony_custom_settings:
6 | - "logdir /var/log/chrony"
7 | - "log tracking"
8 | timesync_ntp_servers:
9 | - hostname: 172.16.123.1
10 | - hostname: 172.16.123.2
11 | iburst: true
12 | minpoll: 4
13 | - hostname: 172.16.123.3
14 | pool: true
15 | iburst: true
16 | minpoll: 4
17 | maxpoll: 6
18 | timesync_ntp_provider: chrony
19 | timesync_step_threshold: 0.01
20 | timesync_dhcp_ntp_servers: true
21 | timesync_min_sources: 2
22 |
23 | tasks:
24 | - name: Run the role
25 | include_role:
26 | name: linux-system-roles.timesync
27 | public: true
28 |
29 | - name: Run chrony tests
30 | tags: tests::verify
31 | block:
32 | - name: Flush handlers
33 | meta: flush_handlers
34 |
35 | - name: Wait for services to start
36 | wait_for:
37 | timeout: 2
38 |
39 | - name: Get list of currently used time sources
40 | shell: chronyc -n sources || ntpq -pn
41 | register: sources
42 | changed_when: false
43 |
44 | - name: Check time sources
45 | assert:
46 | that:
47 | - "'172.16.123.1' in sources.stdout"
48 | - "'172.16.123.2' in sources.stdout"
49 | - "'172.16.123.3' in sources.stdout"
50 |
51 | - name: Get list of log files
52 | command: ls /var/log/chrony/
53 | register: logfiles
54 | changed_when: false
55 |
56 | - name: Check log generated files
57 | assert:
58 | that:
59 | - "'tracking.log' in logfiles.stdout"
60 |
61 | - name: Check headers for ansible_managed, fingerprint
62 | include_tasks: tasks/check_header.yml
63 | loop:
64 | - "{{ timesync_chrony_conf_path }}"
65 | - "{{ timesync_chrony_sysconfig_path }}"
66 | loop_control:
67 | loop_var: __file
68 | vars:
69 | __fingerprint: "system_role:timesync"
70 |
71 | always:
72 | - name: Cleanup after tests
73 | include_tasks: tasks/cleanup.yml
74 |
--------------------------------------------------------------------------------
/tests/tests_default.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Ensure that the role runs with default parameters
3 | hosts: all
4 | gather_facts: false
5 | roles:
6 | - linux-system-roles.timesync
7 |
--------------------------------------------------------------------------------
/tests/tests_default_vars.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Ensure that the role declares all parameters in defaults
3 | hosts: all
4 | tasks:
5 | - name: Include the timesync role
6 | include_role:
7 | name: linux-system-roles.timesync
8 | public: true
9 |
10 | - name: Check that public vars are defined
11 | assert:
12 | that: vars[item] is defined
13 | loop:
14 | - timesync_ntp_servers
15 | - timesync_ptp_domains
16 | - timesync_dhcp_ntp_servers
17 | - timesync_step_threshold
18 | - timesync_min_sources
19 | - timesync_ntp_hwts_interfaces
20 | - timesync_ntp_provider
21 | - timesync_max_distance
22 | - timesync_ntp_ip_family
23 |
--------------------------------------------------------------------------------
/tests/tests_default_wrapper.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Create static inventory from hostvars
3 | tags:
4 | - 'tests::slow'
5 | hosts: all
6 | tasks:
7 | - name: Create temporary file
8 | tempfile:
9 | state: file
10 | suffix: .inventory.yaml
11 | register: tempinventory
12 | delegate_to: localhost
13 |
14 | - name: Create static inventory from hostvars
15 | template:
16 | src: inventory.yaml.j2
17 | dest: "{{ tempinventory.path }}"
18 | mode: '0644'
19 | delegate_to: localhost
20 |
21 | - name: Run tests_default.yml normally
22 | tags:
23 | - 'tests::slow'
24 | import_playbook: tests_default.yml
25 |
26 | - name: Run tests_default.yml in check_mode
27 | tags:
28 | - 'tests::slow'
29 | hosts: all
30 | tasks:
31 | - name: Run ansible-playbook with tests_default.yml in check mode
32 | command: >-
33 | {{ __ap_cmd | quote }} -vvv -i {{ tempinventory.path }}
34 | --check tests_default.yml
35 | changed_when: false
36 | delegate_to: localhost
37 | vars:
38 | __ap_cmd: "{{ ansible_playbook_filepath | d('ansible-playbook') }}"
39 |
40 | - name: Remove the temporary file
41 | file:
42 | path: "{{ tempinventory.path }}"
43 | state: absent
44 | when: tempinventory.path is defined
45 | delegate_to: localhost
46 |
--------------------------------------------------------------------------------
/tests/tests_ntp.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Configure time synchronization with NTP servers
3 | hosts: all
4 | vars:
5 | timesync_ntp_servers:
6 | - hostname: 172.16.123.1
7 | - hostname: 172.16.123.2
8 | iburst: false
9 | prefer: false
10 | trust: false
11 | minpoll: 4
12 | - hostname: 172.16.123.3
13 | pool: true
14 | iburst: true
15 | minpoll: 4
16 | maxpoll: 6
17 | prefer: true
18 | trust: true
19 | xleave: true
20 | filter: 3
21 | timesync_step_threshold: 0.01
22 | timesync_dhcp_ntp_servers: true
23 | timesync_min_sources: 2
24 | timesync_ntp_hwts_interfaces: ["*"]
25 | tasks:
26 | - name: Run the role
27 | include_role:
28 | name: linux-system-roles.timesync
29 | public: true
30 |
31 | - name: Run test
32 | tags: tests::verify
33 | block:
34 | - name: Flush handlers
35 | meta: flush_handlers
36 |
37 | - name: Wait for services to start
38 | wait_for:
39 | timeout: 2
40 |
41 | - name: Get list of currently used time sources
42 | shell: chronyc -n sources || ntpq -pn
43 | register: sources
44 | changed_when: false
45 |
46 | - name: Check time sources
47 | assert:
48 | that:
49 | - "'172.16.123.1' in sources.stdout"
50 | - "'172.16.123.2' in sources.stdout"
51 | - "'172.16.123.3' in sources.stdout"
52 |
53 | - name: Fetch chrony.conf file
54 | slurp:
55 | src: /etc/chrony.conf
56 | when: "'LastRx' in sources.stdout"
57 | register: chrony_conf_encoded
58 |
59 | - name: Fetch ntp.conf file
60 | slurp:
61 | src: /etc/ntp.conf
62 | when: "'LastRx' not in sources.stdout"
63 | register: ntp_conf_encoded
64 |
65 | - name: Decode chrony.conf file
66 | set_fact:
67 | chrony_conf: "{{ chrony_conf_encoded.content | b64decode }}"
68 | when: chrony_conf_encoded is not skipped
69 |
70 | - name: Decode ntp.conf file
71 | set_fact:
72 | ntp_conf: "{{ ntp_conf_encoded.content | b64decode }}"
73 | when: ntp_conf_encoded is not skipped
74 |
75 | - name: Check chrony.conf file
76 | assert:
77 | that:
78 | - chrony_conf is not search('172\.16\.123\.1.*iburst')
79 | - chrony_conf is not search('172\.16\.123\.2.*iburst')
80 | - chrony_conf is search('172\.16\.123\.3.*iburst')
81 | - chrony_conf is not search('172\.16\.123\.1.*prefer')
82 | - chrony_conf is not search('172\.16\.123\.2.*prefer')
83 | - chrony_conf is search('172\.16\.123\.3.*prefer')
84 | - chrony_conf is not search('172\.16\.123\.1.*trust')
85 | - chrony_conf is not search('172\.16\.123\.2.*trust')
86 | - chrony_conf is search('172\.16\.123\.3.*trust')
87 | - chrony_conf is not search('172\.16\.123\.1.*xleave')
88 | - chrony_conf is not search('172\.16\.123\.2.*xleave')
89 | - chrony_conf is search('172\.16\.123\.3.*xleave') ==
90 | __timesync_chrony_version is version('3.0', '>=')
91 | - chrony_conf is not search('172\.16\.123\.1.*filter')
92 | - chrony_conf is not search('172\.16\.123\.2.*filter')
93 | - chrony_conf is search('172\.16\.123\.3.*filter 3') ==
94 | __timesync_chrony_version is version('3.4', '>=')
95 | - chrony_conf is search('hwtimestamp \*') ==
96 | __timesync_chrony_version is version('3.0', '>=')
97 | - chrony_conf is search('hwtimestamp .* minpoll 0') ==
98 | __timesync_chrony_version is version('3.1', '>=')
99 | when: chrony_conf is defined
100 |
101 | - name: Check ntp.conf file
102 | assert:
103 | that:
104 | - ntp_conf is not search('172\.16\.123\.1.*iburst')
105 | - ntp_conf is not search('172\.16\.123\.2.*iburst')
106 | - ntp_conf is search('172\.16\.123\.3.*iburst')
107 | - ntp_conf is not search('172\.16\.123\.1.*prefer')
108 | - ntp_conf is not search('172\.16\.123\.2.*prefer')
109 | - ntp_conf is search('172\.16\.123\.3.*prefer')
110 | - ntp_conf is not search('172\.16\.123\.1.*true')
111 | - ntp_conf is not search('172\.16\.123\.2.*true')
112 | - ntp_conf is search('172\.16\.123\.3.*true')
113 | when: ntp_conf is defined
114 |
115 | - name: Check chrony conf for ansible_managed, fingerprint
116 | include_tasks: tasks/check_header.yml
117 | vars:
118 | __file_content: "{{ chrony_conf_encoded }}"
119 | __fingerprint: "system_role:timesync"
120 | when: chrony_conf is defined
121 |
122 | - name: Check chrony sysconf for ansible_managed, fingerprint
123 | include_tasks: tasks/check_header.yml
124 | vars:
125 | __file: "{{ timesync_chrony_sysconfig_path }}"
126 | __fingerprint: "system_role:timesync"
127 | when: chrony_conf is defined
128 |
129 | - name: Check ntp conf for ansible_managed, fingerprint
130 | include_tasks: tasks/check_header.yml
131 | vars:
132 | __file_content: "{{ ntp_conf_encoded }}"
133 | __fingerprint: "system_role:timesync"
134 | when: ntp_conf is defined
135 |
136 | - name: Check ntp sysconf for ansible_managed, fingerprint
137 | include_tasks: tasks/check_header.yml
138 | vars:
139 | __file: "{{ timesync_ntp_sysconfig_path }}"
140 | __fingerprint: "system_role:timesync"
141 | when: ntp_conf is defined
142 |
--------------------------------------------------------------------------------
/tests/tests_ntp_provider1.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Configure NTP with default provider
3 | hosts: all
4 | vars:
5 | timesync_ntp_servers:
6 | - hostname: 172.16.123.1
7 | roles:
8 | - linux-system-roles.timesync
9 |
10 | pre_tasks:
11 | - name: Common test setup tasks
12 | include_tasks: tasks/setup.yml
13 | vars:
14 | __timesync_ostree_unsupported: true
15 |
16 | - name: Remove provider packages
17 | check_mode: false
18 | tags: tests::setup
19 | block:
20 | - name: Remove NTP providers
21 | package:
22 | name: "{{ item }}"
23 | state: absent
24 | with_items:
25 | - chrony
26 | - ntp
27 |
28 | post_tasks:
29 | - name: Verify provider is working
30 | tags: tests::verify
31 | block:
32 | - name: Wait for services to start
33 | wait_for:
34 | timeout: 2
35 |
36 | - name: Get list of currently used time sources
37 | shell: chronyc -n sources || ntpq -pn
38 | register: sources
39 | changed_when: false
40 |
41 | - name: Check time sources
42 | assert:
43 | that:
44 | - "'172.16.123.1' in sources.stdout"
45 |
--------------------------------------------------------------------------------
/tests/tests_ntp_provider2.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Configure NTP with chrony as current provider
3 | hosts: all
4 | vars:
5 | timesync_ntp_servers:
6 | - hostname: 172.16.123.1
7 | roles:
8 | - linux-system-roles.timesync
9 |
10 | pre_tasks:
11 | - name: Common test setup tasks
12 | include_tasks: tasks/setup.yml
13 | vars:
14 | __timesync_ostree_unsupported: true
15 |
16 | - name: Remove the install ntp
17 | check_mode: false
18 | tags: tests::setup
19 | block:
20 | - name: Remove ntp
21 | package:
22 | name: ntp
23 | state: absent
24 |
25 | - name: Install chrony
26 | package:
27 | name: chrony
28 | state: present
29 | register: package_install
30 | ignore_errors: true # noqa ignore-errors
31 |
32 | - name: Skip test if no package
33 | meta: end_play
34 | when: package_install.failed
35 |
36 | - name: Enable chronyd
37 | service:
38 | name: chronyd
39 | state: started
40 | enabled: true
41 |
42 | post_tasks:
43 | - name: Verify chronyd running
44 | tags: tests::verify
45 | block:
46 | - name: Wait for services to start
47 | wait_for:
48 | timeout: 2
49 |
50 | - name: Check chronyd service
51 | command: chronyc -n tracking
52 | changed_when: false
53 |
--------------------------------------------------------------------------------
/tests/tests_ntp_provider3.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Configure NTP with ntp as current provider
3 | hosts: all
4 | vars:
5 | timesync_ntp_servers:
6 | - hostname: 172.16.123.1
7 | roles:
8 | - linux-system-roles.timesync
9 |
10 | pre_tasks:
11 | - name: Common test setup tasks
12 | include_tasks: tasks/setup.yml
13 | vars:
14 | __timesync_ostree_unsupported: true
15 |
16 | - name: Remove then install chrony
17 | check_mode: false
18 | tags: tests::setup
19 | block:
20 | - name: Remove chrony
21 | package:
22 | name: chrony
23 | state: absent
24 |
25 | - name: Install ntp
26 | package:
27 | name: ntp
28 | state: present
29 | register: package_install
30 | ignore_errors: true # noqa ignore-errors
31 |
32 | - name: Skip test if no package
33 | meta: end_play
34 | when: package_install.failed
35 |
36 | - name: Enable ntpd
37 | service:
38 | name: ntpd
39 | state: started
40 | enabled: true
41 |
42 | post_tasks:
43 | - name: Verify ntpd is running
44 | tags: tests::verify
45 | block:
46 | - name: Wait for services to start
47 | wait_for:
48 | timeout: 2
49 |
50 | - name: Check ntpd service
51 | shell: |
52 | set -eu
53 | if set -o | grep -q pipefail; then
54 | set -o pipefail # no pipefail on debian, some ubuntu
55 | fi
56 | ntpq -c rv | grep 'associd=0'
57 | changed_when: false
58 |
--------------------------------------------------------------------------------
/tests/tests_ntp_provider4.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Configure NTP with chrony as specified provider
3 | hosts: all
4 | vars:
5 | timesync_ntp_servers:
6 | - hostname: 172.16.123.1
7 | timesync_ntp_provider: chrony
8 | tasks:
9 | - name: Common test setup tasks
10 | include_tasks: tasks/setup.yml
11 | vars:
12 | __timesync_ostree_unsupported: true
13 |
14 | - name: Install then remove chrony
15 | check_mode: false
16 | tags: tests::setup
17 | block:
18 | - name: Install chrony
19 | package:
20 | name: chrony
21 | state: present
22 | register: package_install
23 | ignore_errors: true # noqa ignore-errors
24 |
25 | - name: Skip test if no package
26 | meta: end_play
27 | when: package_install is failed
28 |
29 | - name: Remove chrony
30 | package:
31 | name: chrony
32 | state: absent
33 |
34 | - name: Run the test
35 | block:
36 | - name: Run the role
37 | include_role:
38 | name: linux-system-roles.timesync
39 | public: true
40 |
41 | - name: Verify chronyd is running
42 | tags: tests::verify
43 | block:
44 | - name: Wait for services to start
45 | wait_for:
46 | timeout: 2
47 |
48 | - name: Check chronyd service
49 | command: chronyc -n tracking
50 | changed_when: false
51 |
52 | always:
53 | - name: Cleanup after tests
54 | include_tasks: tasks/cleanup.yml
55 |
--------------------------------------------------------------------------------
/tests/tests_ntp_provider5.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Configure NTP with ntp as specified provider
3 | hosts: all
4 | vars:
5 | timesync_ntp_servers:
6 | - hostname: 172.16.123.1
7 | timesync_ntp_provider: ntp
8 | tasks:
9 | - name: Common test setup tasks
10 | include_tasks: tasks/setup.yml
11 | vars:
12 | __timesync_ostree_unsupported: true
13 |
14 | - name: Install then remove ntp
15 | check_mode: false
16 | tags: tests::setup
17 | block:
18 | - name: Install ntp
19 | package:
20 | name: ntp
21 | state: present
22 | register: package_install
23 | ignore_errors: true # noqa ignore-errors
24 |
25 | - name: Skip test if no ntp package
26 | meta: end_play
27 | when: package_install.failed
28 |
29 | - name: Remove ntp
30 | package:
31 | name: ntp
32 | state: absent
33 |
34 | - name: Run test
35 | block:
36 | - name: Run the role
37 | include_role:
38 | name: linux-system-roles.timesync
39 | public: true
40 |
41 | - name: Verify ntpd service
42 | tags: tests::verify
43 | block:
44 | - name: Wait for services to start
45 | wait_for:
46 | timeout: 2
47 |
48 | - name: Check ntpd service
49 | shell: |
50 | set -eu
51 | if set -o | grep -q pipefail; then
52 | set -o pipefail # no pipefail on debian, some ubuntu
53 | fi
54 | ntpq -c rv | grep 'associd=0'
55 | changed_when: false
56 |
57 | always:
58 | - name: Cleanup after tests
59 | include_tasks: tasks/cleanup.yml
60 |
--------------------------------------------------------------------------------
/tests/tests_ntp_provider6.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: >-
3 | Configure NTP with OS release non-default provider and
4 | then change it to the default provider
5 | hosts: all
6 | gather_facts: true
7 | vars:
8 | is_ntp_default: "{{ ansible_distribution in ['RedHat', 'CentOS']
9 | and ansible_distribution_version is version('7.0', '<') }}"
10 | both_avail: true
11 |
12 | tasks:
13 | - name: Common test setup tasks
14 | include_tasks: tasks/setup.yml
15 | vars:
16 | __timesync_ostree_unsupported: true
17 |
18 | - name: See if both providers are available
19 | check_mode: false
20 | tags: tests::setup
21 | block:
22 | - name: Check for availability of both NTP providers
23 | package:
24 | name: "{{ item }}"
25 | state: present
26 | register: package_install
27 | ignore_errors: true # noqa ignore-errors
28 | with_items:
29 | - chrony
30 | - ntp
31 |
32 | # meta doesn't pickup with_item in when conditional,
33 | # following set_fact workarounds that
34 | # see https://github.com/ansible/ansible/issues/35890
35 | - name: Set the availability of both NTP providers
36 | set_fact:
37 | both_avail: false
38 | when: item.failed
39 | with_items:
40 | - "{{ package_install.results }}"
41 |
42 | - name: End test if not both available
43 | meta: end_play
44 | when: not both_avail
45 |
46 | - name: Remove NTP providers
47 | package:
48 | name: "{{ item }}"
49 | state: absent
50 | with_items:
51 | - chrony
52 | - ntp
53 |
54 | - name: Call role to change provider
55 | include_role:
56 | name: linux-system-roles.timesync
57 | public: true
58 | vars:
59 | # ntp is the default choice for RedHat and CentOS
60 | # version < 7.0 - reverse it
61 | timesync_ntp_provider: "{{ 'chrony' if is_ntp_default else 'ntp' }}"
62 |
63 | - name: Verify provider set correctly
64 | tags: tests::verify
65 | block:
66 | - name: Flush handlers
67 | meta: flush_handlers
68 |
69 | - name: Wait for services to start
70 | wait_for:
71 | timeout: 2
72 |
73 | - name: Check chronyd service
74 | command: chronyc -n tracking
75 | when: is_ntp_default | bool
76 | changed_when: false
77 |
78 | - name: Check ntpd service
79 | shell: |
80 | set -eu
81 | if set -o | grep -q pipefail; then
82 | set -o pipefail # no pipefail on debian, some ubuntu
83 | fi
84 | ntpq -c rv | grep 'associd=0'
85 | when: not is_ntp_default
86 | changed_when: false
87 |
88 | - name: Call role to reset default provider
89 | include_role:
90 | name: linux-system-roles.timesync
91 | vars:
92 | timesync_ntp_provider: "{{ timesync_ntp_provider_os_default }}"
93 |
94 | - name: Verify provider set correctly - 2
95 | tags: tests::verify
96 | block:
97 | - name: Wait for services to start
98 | wait_for:
99 | timeout: 2
100 |
101 | - name: Check ntpd service
102 | shell: |
103 | set -eu
104 | if set -o | grep -q pipefail; then
105 | set -o pipefail # no pipefail on debian, some ubuntu
106 | fi
107 | ntpq -c rv | grep 'associd=0'
108 | when: is_ntp_default | bool
109 | changed_when: false
110 |
111 | - name: Check chronyd service
112 | command: chronyc -n tracking
113 | when: not is_ntp_default
114 | changed_when: false
115 |
--------------------------------------------------------------------------------
/tests/tests_ntp_ptp.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Configure time synchronization with NTP servers and PTP domains
3 | hosts: all
4 | gather_facts: true
5 | vars:
6 | timesync_ntp_servers:
7 | - hostname: 172.16.123.1
8 | minpoll: 0
9 | maxpoll: 2
10 | - hostname: 172.16.123.2
11 | minpoll: 0
12 | maxpoll: 2
13 | timesync_ptp_domains:
14 | - number: 0
15 | interfaces: "{{ [ ansible_default_ipv4['interface'] ] }}"
16 | delay: 0.0001
17 | - number: 1
18 | interfaces: "{{ [ ansible_default_ipv4['interface'] ] }}"
19 | delay: 0.0001
20 | timesync_step_threshold: 0.001
21 | timesync_dhcp_ntp_servers: false
22 | timesync_min_sources: 2
23 | tasks:
24 | - name: Run test
25 | tags: tests::verify
26 | block:
27 | - name: Common test setup tasks
28 | include_tasks: tasks/setup.yml
29 |
30 | - name: Run role
31 | include_role:
32 | name: linux-system-roles.timesync
33 | public: true
34 |
35 | - name: Flush handlers
36 | meta: flush_handlers
37 |
38 | - name: Ensure ethtool is installed
39 | package:
40 | name: ethtool
41 | state: present
42 | use: "{{ (__timesync_is_ostree | d(false)) |
43 | ternary('ansible.posix.rhel_rpm_ostree', omit) }}"
44 |
45 | - name: Check if SW/HW timestamping is supported
46 | command: ethtool -T "{{ ansible_default_ipv4['interface'] }}"
47 | register: ethtool
48 | ignore_errors: true # noqa ignore-errors
49 | changed_when: false
50 |
51 | - name: Run test
52 | when: "'ware-transmit' in ethtool.stdout"
53 | block:
54 | - name: Wait for services to start
55 | wait_for:
56 | timeout: 2
57 |
58 | - name: Get list of currently used time sources
59 | shell: chronyc -n sources || ntpq -pn
60 | register: sources
61 | changed_when: false
62 |
63 | - name: Check time sources
64 | assert:
65 | that:
66 | - "'172.16.123.1' in sources.stdout"
67 | - "'172.16.123.2' in sources.stdout"
68 | - "'PTP0' in sources.stdout"
69 | - "'PTP1' in sources.stdout"
70 |
71 | always:
72 | - name: Cleanup after tests
73 | include_tasks: tasks/cleanup.yml
74 | vars:
75 | timesync_ntp_servers: []
76 | timesync_ptp_domains: []
77 |
--------------------------------------------------------------------------------
/tests/tests_options.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Test setting OPTIONS
3 | hosts: all
4 | gather_facts: true
5 | tasks:
6 | - name: Run tests
7 | block:
8 | - name: Get vars needed to run the tests
9 | include_role:
10 | name: linux-system-roles.timesync
11 | public: true
12 | tasks_from: set_vars.yml
13 |
14 | # install the provider to install the sysconfig file
15 | - name: Install chrony
16 | package:
17 | name: chrony
18 | state: present
19 | use: "{{ (__timesync_is_ostree | d(false)) |
20 | ternary('ansible.posix.rhel_rpm_ostree', omit) }}"
21 | when: timesync_ntp_provider == 'chrony'
22 |
23 | - name: Install ntp
24 | package:
25 | name: ntp
26 | state: present
27 | use: "{{ (__timesync_is_ostree | d(false)) |
28 | ternary('ansible.posix.rhel_rpm_ostree', omit) }}"
29 | when: timesync_ntp_provider == 'ntp'
30 |
31 | - name: Get OPTIONS before running
32 | command: grep ^OPTIONS= {{ timesync_chrony_sysconfig_path }}
33 | changed_when: false
34 | register: __timesync_config_before
35 |
36 | - name: Run role with no arguments to get provider
37 | include_role:
38 | name: linux-system-roles.timesync
39 | public: true
40 |
41 | - name: Get OPTIONS after running
42 | command: grep ^OPTIONS= {{ timesync_chrony_sysconfig_path }}
43 | changed_when: false
44 | register: __timesync_config_after
45 |
46 | - name: Show options
47 | debug:
48 | msg: |
49 | before [{{ __timesync_config_before.stdout }}]
50 | after [{{ __timesync_config_after.stdout }}]
51 |
52 | - name: Ensure that OPTIONS did not change
53 | assert:
54 | that: __timesync_config_before.stdout == __timesync_config_after.stdout
55 |
56 | - name: Try timesync_ntp_ip_family IPv4
57 | include_role:
58 | name: linux-system-roles.timesync
59 | vars:
60 | timesync_ntp_ip_family: IPv4
61 |
62 | - name: Verify IPv4 setting
63 | command: grep 'OPTIONS=.* -4' {{ timesync_chrony_sysconfig_path }}
64 | changed_when: false
65 |
66 | - name: Try timesync_ntp_ip_family IPv6
67 | include_role:
68 | name: linux-system-roles.timesync
69 | vars:
70 | timesync_ntp_ip_family: IPv6
71 |
72 | - name: Verify IPv6 setting
73 | command: grep 'OPTIONS=.* -6' {{ timesync_chrony_sysconfig_path }}
74 | changed_when: false
75 |
76 | always:
77 | - name: Reset OPTIONS
78 | include_role:
79 | name: linux-system-roles.timesync
80 | vars:
81 | timesync_ntp_ip_family: all
82 |
83 | - name: Verify reset
84 | shell: |
85 | set -eux
86 | if grep 'OPTIONS=.* -4' {{ timesync_chrony_sysconfig_path }} || \
87 | grep 'OPTIONS=.* -6' {{ timesync_chrony_sysconfig_path }}; then
88 | echo ERROR: {{ timesync_chrony_sysconfig_path }} has incorrect OPTIONS
89 | exit 1
90 | fi
91 | exit 0
92 | changed_when: false
93 |
--------------------------------------------------------------------------------
/tests/tests_ptp_multi.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Configure time synchronization with multiple PTP domains
3 | hosts: all
4 | gather_facts: true
5 | vars:
6 | timesync_ptp_domains:
7 | - number: 0
8 | interfaces: "{{ [ ansible_default_ipv4['interface'] ] }}"
9 | transport: L2
10 | - number: 1
11 | interfaces: "{{ [ ansible_default_ipv4['interface'] ] }}"
12 | delay: 0.001
13 | transport: UDPv4
14 | hybrid_e2e: true
15 | udp_ttl: 2
16 | timesync_step_threshold: 0.0001
17 | timesync_min_sources: 2
18 | roles:
19 | - linux-system-roles.timesync
20 |
21 | tasks:
22 | - name: Run test
23 | tags: tests::verify
24 | block:
25 | - name: Flush handlers
26 | meta: flush_handlers
27 |
28 | - name: Common test setup tasks
29 | include_tasks: tasks/setup.yml
30 |
31 | - name: Ensure ethtool is installed
32 | package:
33 | name: ethtool
34 | state: present
35 | use: "{{ (__timesync_is_ostree | d(false)) |
36 | ternary('ansible.posix.rhel_rpm_ostree', omit) }}"
37 |
38 | - name: Check if SW/HW timestamping is supported
39 | command: ethtool -T "{{ ansible_default_ipv4['interface'] }}"
40 | register: ethtool
41 | ignore_errors: true # noqa ignore-errors
42 | changed_when: false
43 |
44 | - name: Run test
45 | when: "'ware-transmit' in ethtool.stdout"
46 | block:
47 | - name: Wait for services to start
48 | wait_for:
49 | timeout: 2
50 |
51 | - name: Get list of currently used time sources
52 | shell: chronyc -n sources || ntpq -pn
53 | register: sources
54 | changed_when: false
55 |
56 | - name: Check time sources
57 | assert:
58 | that:
59 | - "'PTP0' in sources.stdout"
60 | - "'PTP1' in sources.stdout"
61 |
62 | - name: Run pmc
63 | vars:
64 | # wokeignore:rule=master
65 | __sock: /var/run/timemaster/ptp4l.0.socket
66 | command: >-
67 | pmc -u -b 0 -d 0 -s "{{ __sock }}" 'GET DOMAIN'
68 | 'GET PORT_DATA_SET'
69 | register: pmc
70 | changed_when: false
71 |
72 | - name: Check PTP domain
73 | assert:
74 | that:
75 | - "'domainNumber 0' in pmc.stdout"
76 |
77 | - name: Check PTP port state
78 | assert:
79 | that:
80 | - pmc.stdout is search("portState\s+LISTENING")
81 | when:
82 | - ansible_distribution not in ['RedHat', 'CentOS'] or
83 | ansible_distribution_version is not version('8.3', '<')
84 |
85 | - name: Run pmc
86 | vars:
87 | # wokeignore:rule=master
88 | __sock: /var/run/timemaster/ptp4l.1.socket
89 | command: >-
90 | pmc -u -b 0 -d 1 -s "{{ __sock }}" 'GET DOMAIN'
91 | 'GET PORT_DATA_SET'
92 | register: pmc
93 | changed_when: false
94 |
95 | - name: Check PTP domain
96 | assert:
97 | that:
98 | - "'domainNumber 1' in pmc.stdout"
99 |
100 | - name: Check PTP port state
101 | assert:
102 | that:
103 | - pmc.stdout is search("portState\s+LISTENING")
104 | when:
105 | - ansible_distribution not in ['RedHat', 'CentOS'] or
106 | ansible_distribution_version is not version('8.3', '<')
107 |
--------------------------------------------------------------------------------
/tests/tests_ptp_single.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Configure time synchronization with single PTP domain
3 | hosts: all
4 | gather_facts: true
5 | vars:
6 | timesync_ptp_domains:
7 | - number: 3
8 | interfaces: "{{ [ ansible_default_ipv4['interface'] ] }}"
9 | roles:
10 | - linux-system-roles.timesync
11 |
12 | tasks:
13 | - name: Run test
14 | tags: tests::verify
15 | block:
16 | - name: Flush handlers
17 | meta: flush_handlers
18 |
19 | - name: Common test setup tasks
20 | include_tasks: tasks/setup.yml
21 |
22 | - name: Ensure ethtool is installed
23 | package:
24 | name: ethtool
25 | state: present
26 | use: "{{ (__timesync_is_ostree | d(false)) |
27 | ternary('ansible.posix.rhel_rpm_ostree', omit) }}"
28 |
29 | - name: Check if SW/HW timestamping is supported
30 | command: ethtool -T "{{ ansible_default_ipv4['interface'] }}"
31 | register: ethtool
32 | ignore_errors: true # noqa ignore-errors
33 | changed_when: false
34 |
35 | - name: Run test
36 | when: "'ware-transmit' in ethtool.stdout"
37 | block:
38 | - name: Wait for services to start
39 | wait_for:
40 | timeout: 2
41 |
42 | - name: Run pmc
43 | command: pmc -u -b 0 -d 3 'GET DOMAIN' 'GET PORT_DATA_SET'
44 | register: pmc
45 | changed_when: false
46 |
47 | - name: Check PTP domain
48 | assert:
49 | that:
50 | - "'domainNumber 3' in pmc.stdout"
51 |
52 | - name: Check PTP port state
53 | assert:
54 | that:
55 | - pmc.stdout is search("portState\s+LISTENING")
56 | when:
57 | - ansible_distribution not in ['RedHat', 'CentOS'] or
58 | ansible_distribution_version is not version('8.3', '<')
59 |
--------------------------------------------------------------------------------
/tests/vars/rh_distros_vars.yml:
--------------------------------------------------------------------------------
1 | # vars for handling conditionals for RedHat and clones
2 | # DO NOT EDIT - file is auto-generated
3 | # repo is https://github.com/linux-system-roles/.github
4 | # file is playbooks/templates/tests/vars/rh_distros_vars.yml
5 | ---
6 | # Ansible distribution identifiers that the role treats like RHEL
7 | __timesync_rh_distros:
8 | - AlmaLinux
9 | - CentOS
10 | - RedHat
11 | - Rocky
12 |
13 | # Same as above but includes Fedora
14 | __timesync_rh_distros_fedora: "{{ __timesync_rh_distros + ['Fedora'] }}"
15 |
16 | # Use this in conditionals to check if distro is Red Hat or clone
17 | __timesync_is_rh_distro: "{{ ansible_distribution in __timesync_rh_distros }}"
18 |
19 | # Use this in conditionals to check if distro is Red Hat or clone, or Fedora
20 | __timesync_is_rh_distro_fedora: "{{ ansible_distribution in __timesync_rh_distros_fedora }}"
21 |
--------------------------------------------------------------------------------
/tox.ini:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: MIT
2 | [lsr_config]
3 | lsr_enable = true
4 |
5 | [lsr_ansible-lint]
6 | configfile = .ansible-lint
7 |
--------------------------------------------------------------------------------
/vars/AlmaLinux_10.yml:
--------------------------------------------------------------------------------
1 | RedHat_10.yml
--------------------------------------------------------------------------------
/vars/AlmaLinux_8.yml:
--------------------------------------------------------------------------------
1 | RedHat_8.yml
--------------------------------------------------------------------------------
/vars/AlmaLinux_9.yml:
--------------------------------------------------------------------------------
1 | RedHat_9.yml
--------------------------------------------------------------------------------
/vars/CentOS_10.yml:
--------------------------------------------------------------------------------
1 | RedHat_10.yml
--------------------------------------------------------------------------------
/vars/CentOS_6.yml:
--------------------------------------------------------------------------------
1 | RedHat_6.yml
--------------------------------------------------------------------------------
/vars/CentOS_7.yml:
--------------------------------------------------------------------------------
1 | RedHat_7.yml
--------------------------------------------------------------------------------
/vars/CentOS_8.yml:
--------------------------------------------------------------------------------
1 | RedHat_8.yml
--------------------------------------------------------------------------------
/vars/CentOS_9.yml:
--------------------------------------------------------------------------------
1 | RedHat_9.yml
--------------------------------------------------------------------------------
/vars/Debian.yml:
--------------------------------------------------------------------------------
1 | ---
2 | timesync_ntp_provider_os_default: "chrony"
3 | timesync_chrony_dhcp_sourcedir: "/run/chrony-dhcp"
4 | timesync_chrony_sysconfig_path: "/etc/default/chrony"
5 | timesync_chrony_sysconfig_options: ""
6 | timesync_chrony_conf_path: "/etc/chrony/chrony.conf"
7 | timesync_ntp_sysconfig_path: "/etc/default/ntp"
8 | timesync_ptp4l_sysconfig_path: ""
9 | timesync_phc2sys_sysconfig_path: ""
10 | # wokeignore:rule=master
11 | timesync_timemaster_config_path: "/etc/linuxptp/timemaster.conf"
12 |
--------------------------------------------------------------------------------
/vars/Fedora.yml:
--------------------------------------------------------------------------------
1 | ---
2 | timesync_ntp_provider_os_default: chrony
3 | timesync_chrony_dhcp_sourcedir: /run/chrony-dhcp
4 | timesync_chrony_sysconfig_path: /etc/sysconfig/chronyd
5 | timesync_chrony_sysconfig_options: "-F 2"
6 | timesync_chrony_conf_path: "/etc/chrony.conf"
7 | timesync_ntp_sysconfig_path: /etc/sysconfig/ntpd
8 | timesync_ptp4l_sysconfig_path: /etc/sysconfig/ptp4l
9 | timesync_phc2sys_sysconfig_path: /etc/sysconfig/phc2sys
10 | # wokeignore:rule=master
11 | timesync_timemaster_config_path: /etc/timemaster.conf
12 |
--------------------------------------------------------------------------------
/vars/OracleLinux_10.yml:
--------------------------------------------------------------------------------
1 | RedHat_10.yml
--------------------------------------------------------------------------------
/vars/OracleLinux_6.yml:
--------------------------------------------------------------------------------
1 | RedHat_6.yml
--------------------------------------------------------------------------------
/vars/OracleLinux_7.yml:
--------------------------------------------------------------------------------
1 | RedHat_7.yml
--------------------------------------------------------------------------------
/vars/OracleLinux_8.yml:
--------------------------------------------------------------------------------
1 | RedHat_8.yml
--------------------------------------------------------------------------------
/vars/OracleLinux_9.yml:
--------------------------------------------------------------------------------
1 | RedHat_9.yml
--------------------------------------------------------------------------------
/vars/RedHat_10.yml:
--------------------------------------------------------------------------------
1 | ---
2 | timesync_ntp_provider_os_default: chrony
3 | timesync_chrony_dhcp_sourcedir: /run/chrony-dhcp
4 | timesync_chrony_sysconfig_path: /etc/sysconfig/chronyd
5 | timesync_chrony_sysconfig_options: "-F 2"
6 | timesync_chrony_conf_path: "/etc/chrony.conf"
7 | timesync_ntp_sysconfig_path: /etc/sysconfig/ntpd
8 | timesync_ptp4l_sysconfig_path: /etc/sysconfig/ptp4l
9 | timesync_phc2sys_sysconfig_path: /etc/sysconfig/phc2sys
10 | # wokeignore:rule=master
11 | timesync_timemaster_config_path: /etc/timemaster.conf
12 |
--------------------------------------------------------------------------------
/vars/RedHat_6.yml:
--------------------------------------------------------------------------------
1 | ---
2 | timesync_ntp_provider_os_default: ntp
3 | timesync_chrony_dhcp_sourcedir: ""
4 | timesync_chrony_sysconfig_path: /etc/sysconfig/chronyd
5 | timesync_chrony_sysconfig_options: ""
6 | timesync_chrony_conf_path: "/etc/chrony.conf"
7 | timesync_ntp_sysconfig_path: /etc/sysconfig/ntpd
8 | timesync_ptp4l_sysconfig_path: /etc/sysconfig/ptp4l
9 | timesync_phc2sys_sysconfig_path: /etc/sysconfig/phc2sys
10 | # wokeignore:rule=master
11 | timesync_timemaster_config_path: /etc/timemaster.conf
12 |
--------------------------------------------------------------------------------
/vars/RedHat_7.yml:
--------------------------------------------------------------------------------
1 | ---
2 | timesync_ntp_provider_os_default: chrony
3 | timesync_chrony_dhcp_sourcedir: ""
4 | timesync_chrony_sysconfig_path: /etc/sysconfig/chronyd
5 | timesync_chrony_sysconfig_options: ""
6 | timesync_chrony_conf_path: "/etc/chrony.conf"
7 | timesync_ntp_sysconfig_path: /etc/sysconfig/ntpd
8 | timesync_ptp4l_sysconfig_path: /etc/sysconfig/ptp4l
9 | timesync_phc2sys_sysconfig_path: /etc/sysconfig/phc2sys
10 | # wokeignore:rule=master
11 | timesync_timemaster_config_path: /etc/timemaster.conf
12 |
--------------------------------------------------------------------------------
/vars/RedHat_8.yml:
--------------------------------------------------------------------------------
1 | ---
2 | timesync_ntp_provider_os_default: chrony
3 | timesync_chrony_dhcp_sourcedir: ""
4 | timesync_chrony_sysconfig_path: /etc/sysconfig/chronyd
5 | timesync_chrony_sysconfig_options: ""
6 | timesync_chrony_conf_path: "/etc/chrony.conf"
7 | timesync_ntp_sysconfig_path: /etc/sysconfig/ntpd
8 | timesync_ptp4l_sysconfig_path: /etc/sysconfig/ptp4l
9 | timesync_phc2sys_sysconfig_path: /etc/sysconfig/phc2sys
10 | # wokeignore:rule=master
11 | timesync_timemaster_config_path: /etc/timemaster.conf
12 |
--------------------------------------------------------------------------------
/vars/RedHat_9.yml:
--------------------------------------------------------------------------------
1 | ---
2 | timesync_ntp_provider_os_default: chrony
3 | timesync_chrony_dhcp_sourcedir: /run/chrony-dhcp
4 | timesync_chrony_sysconfig_path: /etc/sysconfig/chronyd
5 | timesync_chrony_sysconfig_options: "-F 2"
6 | timesync_chrony_conf_path: "/etc/chrony.conf"
7 | timesync_ntp_sysconfig_path: /etc/sysconfig/ntpd
8 | timesync_ptp4l_sysconfig_path: /etc/sysconfig/ptp4l
9 | timesync_phc2sys_sysconfig_path: /etc/sysconfig/phc2sys
10 | # wokeignore:rule=master
11 | timesync_timemaster_config_path: /etc/timemaster.conf
12 |
--------------------------------------------------------------------------------
/vars/Rocky_10.yml:
--------------------------------------------------------------------------------
1 | RedHat_10.yml
--------------------------------------------------------------------------------
/vars/Rocky_8.yml:
--------------------------------------------------------------------------------
1 | RedHat_8.yml
--------------------------------------------------------------------------------
/vars/Rocky_9.yml:
--------------------------------------------------------------------------------
1 | RedHat_9.yml
--------------------------------------------------------------------------------
/vars/SL-Micro.yml:
--------------------------------------------------------------------------------
1 | ---
2 | timesync_ntp_provider_os_default: chrony
3 | timesync_chrony_dhcp_sourcedir: /run/chrony-dhcp
4 | timesync_chrony_sysconfig_path: /etc/sysconfig/chronyd
5 | timesync_chrony_sysconfig_options: ""
6 | timesync_chrony_conf_path: "/etc/chrony.conf"
7 | timesync_ntp_sysconfig_path: /etc/sysconfig/ntpd
8 | timesync_ptp4l_sysconfig_path: /etc/sysconfig/ptp4l
9 | timesync_phc2sys_sysconfig_path: /etc/sysconfig/phc2sys
10 | # wokeignore:rule=master
11 | timesync_timemaster_config_path: /etc/timemaster.conf
12 |
--------------------------------------------------------------------------------
/vars/default.yml:
--------------------------------------------------------------------------------
1 | ---
2 | timesync_ntp_provider_os_default: chrony
3 | timesync_chrony_dhcp_sourcedir: ""
4 | timesync_chrony_sysconfig_path: /etc/sysconfig/chronyd
5 | timesync_chrony_sysconfig_options: ""
6 | timesync_chrony_conf_path: "/etc/chrony.conf"
7 | timesync_ntp_sysconfig_path: /etc/sysconfig/ntpd
8 | timesync_ptp4l_sysconfig_path: /etc/sysconfig/ptp4l
9 | timesync_phc2sys_sysconfig_path: /etc/sysconfig/phc2sys
10 | # wokeignore:rule=master
11 | timesync_timemaster_config_path: /etc/timemaster.conf
12 |
--------------------------------------------------------------------------------
/vars/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | __timesync_chrony_version: "{{
3 | ansible_facts.packages['chrony'][0].version | default('0')
4 | if 'chrony' in ansible_facts.packages else '0' }}"
5 | __timesync_ntp_version: "{{
6 | ansible_facts.packages['ntp'][0].version | default('0')
7 | if 'ntp' in ansible_facts.packages else '0' }}"
8 |
9 | # ansible_facts required by the role
10 | __timesync_required_facts:
11 | - distribution
12 | - distribution_major_version
13 | - distribution_version
14 | - os_family
15 |
16 | # the subsets of ansible_facts that need to be gathered in case any of the
17 | # facts in required_facts is missing; see the documentation of
18 | # the 'gather_subset' parameter of the 'setup' module
19 | __timesync_required_facts_subsets: "{{ ['!all', '!min'] +
20 | __timesync_required_facts }}"
21 |
22 | # BEGIN - DO NOT EDIT THIS BLOCK - rh distros variables
23 | # Ansible distribution identifiers that the role treats like RHEL
24 | __timesync_rh_distros:
25 | - AlmaLinux
26 | - CentOS
27 | - RedHat
28 | - Rocky
29 |
30 | # Same as above but includes Fedora
31 | __timesync_rh_distros_fedora: "{{ __timesync_rh_distros + ['Fedora'] }}"
32 |
33 | # Use this in conditionals to check if distro is Red Hat or clone
34 | __timesync_is_rh_distro: "{{ ansible_distribution in __timesync_rh_distros }}"
35 |
36 | # Use this in conditionals to check if distro is Red Hat or clone, or Fedora
37 | __timesync_is_rh_distro_fedora: "{{ ansible_distribution in __timesync_rh_distros_fedora }}"
38 | # END - DO NOT EDIT THIS BLOCK - rh distros variables
39 |
--------------------------------------------------------------------------------