Compare commits

...

74 Commits

Author SHA1 Message Date
Thomas Woerner
d580431832 Merge pull request #1290 from rjeffman/multiple_sudorule
ipasudorule: Add support for batch mode and multiple sudorules
2024-11-19 14:55:40 +01:00
Rafael Guterres Jeffman
6c94fe9bd5 tests/sudorule: Don't become or gather_facts and use only true/false
Unless there's a real need to use privileged access or to gather Ansible
facts upfront, we should always set "become: false" and
"gather_facts: false". In the case that only a few Ansible facts are
required, 'ansible.builtin.setup' with 'gather_subset' should be used.

As the YAML 1.2 standard dictates, boolean values should only use 'true'
or 'false' values.

This patch fixes these issues in the 'sudorule' test suite.
2024-11-18 11:59:51 -03:00
Rafael Guterres Jeffman
4fa0621156 ipasudorule: Add support for batch mode and multiple sudorules
Currently, ipasudorule must add or modify a single sudorule at a time,
incurring in more load in the server if there are many rules to be
processed.

This patch adds suport for adding multiple sudorules in one playbook
task by using the parameter 'sudorules' and defining a list of sudorules
configurations to be ensured.

As multiple sudorules will be processed, the patch also enables batch
mode processing of sudorules, trying to reduce the load on the server.

Test 'tests/sudorule/test_sudorule_client_context.yml' was modified to
include tasks with 'sudorules' to be executed both on the server or on
the client context.

New tests were added to the sudorule test suite:

    tests/sudorule/test_sudorules.yml
    tests/sudorule/test_sudorules_member_case_insensitive.yml
2024-11-18 11:59:21 -03:00
Rafael Guterres Jeffman
da775a21b2 ansible_freeipa_module_utils: Add EntryFactory class
This patch adds the class EntryFactory to the ansible-freeipa module
utils. This class allows the handling of modules with multiple object
entries as list of objects. When the multi-object parameter is not used,
it creates a list of a single object, allowing for the same code idiom
to be used.

The entries created can be used both as objects, by acessing the values
as properties, or as dictionaires, by accessing the elements as
key-value pairs.
2024-11-15 08:43:19 -03:00
Thomas Woerner
5a774d2612 Merge pull request #1306 from rjeffman/use_azure_loops
upstream CI: Use Azure 'loops' to create stages
2024-11-13 16:24:29 +01:00
Rafael Guterres Jeffman
3e405fd08d upstream CI: Use Azure 'loops' to create stages
This patch modify the pipelines to create stages using the 'each'
expression on Azure pipelines, so that the configuration and the list of
distributions can be set using variables.

Testing CentOS 8 Stream and Galaxy collections still need to be handled
in a separate group, although, the pipeline configuration becomes easily
changed, specially when updating Ansible versions.
2024-11-13 11:08:36 -03:00
Thomas Woerner
cb3226910b Merge pull request #1311 from rjeffman/consistent_cli_arguments
infra/image/build.sh: Use consistent options for hostname
2024-11-12 12:45:30 +01:00
Rafael Guterres Jeffman
a96611fb3f infra/image/build.sh: Use consistent options for hostname
This patch makes the CLI argument for setting the image hostname
consistent with 'start.sh', settling on '-n HOSTNAME' for both scripts.
2024-11-12 08:35:46 -03:00
Thomas Woerner
e92f09b920 Merge pull request #1308 from rjeffman/mv_set_test_modules
upstream CI: Move scripts that evaluate repo changes to infra/azure
2024-11-07 10:14:50 +01:00
Thomas Woerner
97b0638f30 Merge pull request #1310 from rjeffman/remove_pydocstyle
linters: Remove pydocstyle from linter checks
2024-11-07 10:04:21 +01:00
Rafael Guterres Jeffman
24569b850a linters: Remove pydocstyle from linter checks
Pydocstyle has been deprecated is no longer in development. It is also
not a requirement for Ansible tests.

This patch removes pydocstyle from current checks performed.
2024-11-06 15:15:53 -03:00
Rafael Guterres Jeffman
08a2ba1592 Merge pull request #1281 from t-woerner/multi_user_test_generate_test_data
tests/user/test_users_present_*: Use new generate_test_data.yml
2024-11-04 14:19:19 -03:00
Rafael Guterres Jeffman
3d5ff1f5fd Merge pull request #1298 from t-woerner/fixipaip_no_hard_coded_adminpassword
fixipaip infra image service: No need for hard coded admin password
2024-11-04 14:09:00 -03:00
Rafael Guterres Jeffman
2b28626012 Merge pull request #1275 from t-woerner/drop_superfluous_test_services_absent
test_services_absent is also part of test_services_present, not needed
2024-11-04 14:06:58 -03:00
Thomas Woerner
7c7d98872e Merge pull request #1309 from rjeffman/update_fedora_41
Update images to Fedora 41
2024-11-04 15:38:15 +01:00
Rafael Guterres Jeffman
8956a7a1dd build images: Force use --privileged on containers
Deploying FreeIPA in the testing containers requires privileged access.
2024-11-04 11:21:08 -03:00
Rafael Guterres Jeffman
25577fa9bc build images: Update images for Fedora 41
Fedora has released version 41, which was the previous 'rawhide'
version, and now the 'fedora-latest' requires dnf5 related packages.
2024-11-04 11:21:08 -03:00
Rafael Guterres Jeffman
f6bd62feb4 upstream CI: Move scripts that evaluate repo changes to infra/azure
All scripts related to the Azure CI now reside on inrfa/azure, but the
scripts that evaluate the changes made against ansible-freeipa's main
development branch.

This patch move these scripts to the proper locations.
2024-10-31 19:17:20 -03:00
Thomas Woerner
33c1c00643 Merge pull request #1300 from rjeffman/update_upstream_ci
Fix upstream CI and remove molecule
2024-10-31 15:23:41 +01:00
Rafael Guterres Jeffman
0f530df092 upstream CI: Update Ansible version
ansible-core versions 2.15 and 2.16 and used for all pipelines, but
version 2.17 is not used for CentOS 8 Stream, as platform python on
this version is 3.6 which is not supported in this ansible-core version.
2024-10-31 11:06:41 -03:00
Rafael Guterres Jeffman
a707d1887d upstream CI: Use Ubuntu 24.04 to build test images 2024-10-31 11:06:41 -03:00
Rafael Guterres Jeffman
e1786c9ddc upstream CI: Enable creation of CentOS 10 Stream images 2024-10-31 11:06:41 -03:00
Rafael Guterres Jeffman
367d30a30c upstream CI: Simplify pipelines enviroment creation
Several optimizations have been done to the pipelines, to make them
closer to what can be reproduced, with the existing scripts, in a
development environment:

- Use start.sh and build.sh scripts to build and start containers
- Use variables to configure different stages instead of using separate
  files
- Use a commom 'prepare_environment' to create the environment for every
  pipeline
- Use a single file defining testing steps (run_tests.yml)
- Remove Centos 7 pipelines
- Reduce the number of pipelines in the test matrix due to the amount of
  time that tests were using
- Use Azure "loop" (each) to create test groups

The above changes make the pipelines easier to understand and modify.
2024-10-31 11:06:41 -03:00
Rafael Guterres Jeffman
77c34aeca2 upstream ci: Move Azure scripts to infra directory
Move Azure scripts to infra directory, as only roles and modules test
playbooks should exist in the tests directory.
2024-10-31 11:06:41 -03:00
Rafael Guterres Jeffman
5b33cb5e80 Remove molecule dependencies
For some time now, we had some issues with molecule when building test
images for ansible-freeipa, and replaced the image creation with custom
build scripts that use commom container tools (like Dockerfiles and the
build command).

As there's no more tasks that require the use of molecule, this patch
removes the last bits used by it, and fixes documentation and lint
scripts and configuration.
2024-10-31 11:06:41 -03:00
Rafael Guterres Jeffman
c979843b1a upstream CI: Allow podman options when creating containers
When using containers to test ansible-freeipa there's a need to deal
with 'podman' the development environment and the Azure environment. In
the Azure environment, with Ubuntu hosts, using 'cap-add' does not allow
FreeIPA to be installed on the containers, and they need to be executed
with privileged mode. On the other hand, on development environments,
such as recent Fedora hosts, there's no need to run the container with
extra privileges.

This patch modifies the utility function 'container_create' to allow the
usage of key-value argumes such as "cpus=4" and "privileged", that will
be used in the container creation.

The currently available options are "privileged", "cpus", "memory" and
"hostname". By default "cpus=2" and "hostname=ipaserver.test.local".

Also, too make the image build script more self-contained, if the
required Ansible collections are not installed, they will be temporarily
installed so that the image can be built.
2024-10-31 11:06:41 -03:00
Rafael Guterres Jeffman
a8ce235261 utils/set_test_modules: Allow to ignore Git differences
To force setting the IPA_ENABLE_* variables to run all tests, source the
script using '-I' or set the environment variable SKIP_GIT_TESTS to
'True'.

This will allow the correct selection of Azure pipelines tests to be
based on a single environment variable, what will reduce the number of
test running templates to a singe file.
2024-10-30 16:40:26 -03:00
Thomas Woerner
bdcc8153f8 Merge pull request #1305 from rjeffman/ipacert_testfix_key_size
ipacert: Fix ipacert tests
2024-10-30 14:15:38 +01:00
Rafael Guterres Jeffman
57bc35df80 ipacert: Fix ipacert tests
It seems that in recent versions, a minimum of 2048 bits for RSA keys
are required to request a certificate. This seems to be enforced by
crypto policies.

By adjusting the key size all ipacert tests pass.
2024-10-30 08:19:53 -03:00
Thomas Woerner
a2f59e1a34 Merge pull request #1285 from offdutypirate/fix-doc-typos
fix minor typo in hbacrule and hbacsvcgroup docs
2024-10-14 13:08:49 +02:00
Rafael Guterres Jeffman
16636de681 Merge pull request #1268 from t-woerner/ipauser_use_date_string
ipauser: Use date string, not datetime object for expiration dates
2024-10-11 15:30:01 -03:00
Thomas Woerner
55ec25a759 ipauser: Use date string, not datetime object for expiration dates
So far a datetime object was created for the expiration dates
krbpasswordexpiration and krbprincipalexpiration. This resulted in also
sending these objects to the API. With this change, the dates are
converted into strings using the LDAP_GENERALIZED_TIME_FORMAT defined in
ipalib.constants. This way only strings are used with the IPA API.

A new function has been added to ansible_freeipa_module:

- date_string: Convert datetime to gernalized time format string

This fuction is used on the result of user_show to convert the
expiration dates to the gernalized time format string.

The existing function date_format in ansible_freeipa_module has been
renamed to convert_date and fixed in the way that it also uses
date_string to return a gernalized time format string and not a
datetime object. This function was only used in the ipauser module so
far.
2024-10-11 15:52:02 +02:00
Thomas Woerner
2b10256575 test_services_absent is also part of test_services_present, not needed
This test is not needed as it is already part of test_services_present.
2024-10-11 15:51:39 +02:00
Thomas Woerner
907650c746 tests/user/test_users_present_*: Use new generate_test_data.yml
The new generate_test_data.yml is creating the test data with
ansible.builtin.shell and is not calling shell scripts any more. The
generation in the yml file and also the set_fact calls make sure that
the test data is used.
2024-10-11 15:51:14 +02:00
Thomas Woerner
b128a5cb9f fixipaip infra image service: No need for hard coded admin password
The admin password is not needed for the system service as it running
as root. The use of `-e in_server=true` is sufficient for all ipa calls.
2024-10-11 15:50:09 +02:00
Rafael Guterres Jeffman
220c4f0016 Merge pull request #1299 from t-woerner/pylint_github_workflow_disable_too-many-positional-arguments
pylint gihub workflow: Disable too-many-positional-arguments
2024-10-11 10:27:52 -03:00
Thomas Woerner
7f1df9d8f8 pylint gihub workflow: Disable too-many-positional-arguments
This change disables the too-many-positional-arguments message for the
pylint github workflow.
2024-10-11 14:48:59 +02:00
Rafael Guterres Jeffman
75d8ea283f Merge pull request #1292 from t-woerner/new_infra_image_start
New infra image start
2024-10-08 18:56:58 -03:00
Thomas Woerner
91a3013513 Add ansible-freeipa-tests inventory using podman
This inventory file is usable for the containers started with
infra/image/start.sh.
2024-10-02 13:44:09 +02:00
Thomas Woerner
85ef81c842 infra/image/system-service/fixipaip.sh: Behave idempotent
This makes sure that the service is not failing on already applied
modifications.
2024-10-02 13:44:09 +02:00
Thomas Woerner
ad44f11887 infra/image/build.sh: "-s" help fix and cleanup
The help has been fixed for the -s option and the comments about how to
start the container later on has been removed as there will be a script
that is handling this..
2024-10-02 13:44:09 +02:00
Thomas Woerner
80693c431a Use container-ipa.target from freeipa-container container project
This reduces the number of started services in the container. The
fixipaip.service needed to be adapted to ensure that the service is
started properly.

The dockerfiles have been adapted for this change also.
2024-10-02 13:44:09 +02:00
Thomas Woerner
9ebc365d69 Renamed infra/image/inventory to build-inventory, dropped interpreter
This change also removed ansible_python_interpreter setting in the
inventory as the interpreter should be discovered by ansible for the
distributions.

The dockerfiles have been adapted to not force the installation of
python3 for CentOS-Stream 8, 9 and 10.
2024-10-02 13:44:09 +02:00
Thomas Woerner
50ba326ed8 infra/image/build.sh: Use new shcontainer
This removes a lot of duplicate code from the script.
2024-10-02 13:44:09 +02:00
Thomas Woerner
691e5915b9 New infra/image/start.sh script to start the generated containers
The script will try to get the latest image from quay to start it. With
the -l option it will try to use a local image first. This is for example
useful to test changes in the images build script locally.

This also adds infra/image/shcontainer. Some of the content is copied
from utils/shcontainer.
2024-10-02 13:43:37 +02:00
f-trivino
178cf218b9 Merge pull request #1284 from t-woerner/infra_image_system_services_dns_and_kinit
Infra image system services dns and kinit
2024-08-07 15:33:34 +02:00
Thomas Woerner
36f26bdf63 infra/image/system-service/fixipaip.sh: Use of admin for kinit call
The kinit call have been missing the principal.
2024-08-07 14:58:24 +02:00
Thomas Woerner
e2bdbeef6d infra/image system-services: Fix DNS forwarder
The DNS forwarder is set while deploying the IPA server. This forwarder
might not be correct later on.

The old /etc/resolv.conf is copied to /etc/resolv.conf.fixnet by the
fixnet service and later on the fixipaip service is trying to get the
nameserver from the copied file. If the retrieval failed of if the
namesever is 127.0.0.1, then the nameserver will be set to 8.8.8.8.

After fixing the IP addresses for the forward and reverse zone, also the
forwarder is set for the dnsserver "${HOSTNAME}".
2024-08-07 14:58:09 +02:00
f-trivino
88dc4c6923 Merge pull request #1282 from t-woerner/infra_image_enhance_system_services
infra/image/system-services: Enhance checks, also fix reverse zone
2024-08-07 10:54:29 +02:00
Thomas Woerner
e05fbce04c infra/image/system-services: Enhance checks, also fix reverse zone
Checks for IPv4 addresses have been added and reverse zone handling
for fixipaip.sh

The services are logging StandardOutput and StandardError to journal
now.
2024-08-07 10:50:10 +02:00
Jon Moore
c2ff12b101 fix minor typo in hbacrule and hbacsvcgroup docs
Signed-off-by: Jon Moore <jonmoore@redhat.com>
2024-08-06 16:03:21 -05:00
f-trivino
7dbe6edbf0 Merge pull request #1276 from t-woerner/run_containers_ubuntu_24_04_test
Run tests with podman and ubuntu 20.04
2024-08-02 18:35:59 +02:00
Thomas Woerner
02ba890eb4 tests/utils.py: Shorten run_playbook for smaller traceback with assert
Most of the content has been moved to the new function _run_playbook to
reduce the traceback output in the case of a test failure.
2024-08-02 17:21:58 +02:00
Rafael Guterres Jeffman
8515c9a48b upstream ci: Remove 'molecule' from tests.
This patch removes 'molecule' as a dependency for tests, by using the
scripts under `utils` to setup the environment.

By not using molecule, we have more flexibility on using either docker
or podman as the container engine, and makes it easy to reproduce the
environment on different distros, allowing for a more consistent error
reproduction off Azure.
2024-08-02 17:21:58 +02:00
Rafael Guterres Jeffman
94311f439c gitignore: Ignore test results from run-tests.sh 2024-08-02 17:21:58 +02:00
Rafael Guterres Jeffman
7aa9483b2c tests: Allow to set Python interpreter to be used by Ansible
On some systems it is required or desired to run Ansible with a specific
Python interpreter. This patch allows the selection of the Python binary
to use for the pytest playbook tests by setting the environment variable
IPA_PYTHON_PATH. Set it the the full path of the Python interpreter.
2024-08-02 17:21:47 +02:00
Rafael Guterres Jeffman
68bca84481 utils: Rewrite run-tests.sh to use functions and extenal scripts
To modify Azure tests and depend on shell scripts and pytest instead
of molecule, the run-tests.sh script has been rewritten to depend on
bash functions and on a bash script that prepare and start a testing
container.

This patch adds a new script, 'utils/setup_test_container.sh' that
can be used to start a new container, using either podman or docker,
based on the available ansible-freeipa images. The new container can
then be used to run ansible-freeipa tests against it.

Also the following files with bash functions were added, and are
used by both scripts:

    utils/shansible: Functions to run playbooks in the container
    utils/shcontainer: Functions to setup/run a container
    utils/shfun: Generic shell helper functions (e.g.: log)
2024-08-02 17:19:39 +02:00
Thomas Woerner
c9010d52ef Merge pull request #1280 from keestux/fix/ipahost-documentation-correction
README-host.md: correction of managedby_host description
2024-08-02 17:04:48 +02:00
f-trivino
0c6a7c8a14 Merge pull request #1273 from t-woerner/new_image_build_with_podman
New image builder without molecule using podman
2024-07-31 17:09:21 +02:00
Thomas Woerner
0d246b1c11 infra/image/build.sh: Fail if deployment failed or podman is missing
If the deployment was enabled and failed, the script still continued
without failing. If podman was missing it failed without a proper error.

The script now fails and does not enable the services and also does not
commit after the failed deployment. Also is fails if podman is missing.
2024-07-31 16:10:02 +02:00
Rafael Guterres Jeffman
785681f100 ci lint: Allow ShellCheck to test source-d scripts.
As the scripts 'utils/run-tests.sh' and 'utils/setup_test_container.sh'
use some scripts as function libraries, this change forces shellcheck to
also verify those scripts.
2024-07-31 16:10:02 +02:00
Rafael Guterres Jeffman
480c83f504 fixup! New image builder without molecule using podman 2024-07-31 16:10:02 +02:00
Rafael Guterres Jeffman
928ed30b8b ustream ci: Use infra scripts to build testing images
As we do not use molecule features, using a Dockerfile and the
ansible-freeipa deployment roles is enough to create the container
testing images.

This patch removes the usage of molecule in favor of the custom
ansible-freeipa image building script, which allow us to have a similar
process for creating images both on the ustream CI, or on a developer's
environment.

Also, CentOS 7 is removed from the build script, as it in not possible
to run CentOS 7 containers with current versions of systemd.
2024-07-31 16:10:02 +02:00
Rafael Guterres Jeffman
fb6fed58cb rjeffman: this is a fixup for infra/images/build.sh
This patch modifies the image building script by adding:

- An usage message.
- An option "-I" to NOT install IPA to the generated container.
- An opiton "-c NAME" to both set the name and use an existing container
  to ONLY install IPA.
- Rename "scenario" to "DISTRO" as "scenario" should be used for the
  container scenario usage, rather than the distro (I'll change the name
  also in the Azure scripts)
- Use 'log' (from shlog) to print messages.
2024-07-31 16:10:02 +02:00
Rafael Guterres Jeffman
b0e03a032d Add shell utitily functions for scripts
Add two shell libaries with utilities to write shell scripts.

The 'utils/shlog' file provides macro names for ANSI escape sequences to
control color output on terminals, a 'log' functions with pre-defined
behavior for ERROR, WARN, DEBUG, INFO and SUCCESS level messages, and
the 'quiet' function which executes a command and hides its output.

The 'utils/shfun' file provides an interruptinon handler for SIGINT, and
the following functions:

- run_if_exists: run a command if it is available
- cleanup: cleanup environment, possibly stopping a container and a
  Python virtual environment.
- start_virtual_environmnt: initiates a Python virtual environment
- in_python_virtualenv: test if the script is running inside a Python
  virtual environment
- die: abort the script with an error message end exit code 1

New files:

  - utils/shlog
  - utils/shfun
2024-07-31 16:10:02 +02:00
Thomas Woerner
7ac0ec6bd4 tests/azure/templates/build_container.yml: Use new image builder
The new infra/image/build.sh script is used instead of molecule.
2024-07-31 16:10:02 +02:00
Thomas Woerner
8153239ef7 New image builder without molecule using podman
The new image builder is not using molecule and uses podman directly for
the generation of the ansible-test images.

Two additional services are installed to simplify the use of the
container in the test:

- fixnet.service uses /root/fixnet.sh to fix IP address of the server in
  /etc/hosts and to set localhost as the nameserver.
  This service is executed before IPA is started. This eliminates the
  need to restart the IPA server after the container has been started
  and the IPs have been fixed.
- fixipaip.service uses /root/fixipaip.sh to fix the IP address of the
  IPA dnsrecords of server and ipa-ca.

With these services it is now only needed to wait till all services in
the container are started. There is no need to restart the IPA server
anymore. Simply use something like this before starting the tests:

    while [ -n "$(podman exec ansible-test systemctl list-jobs | grep -vi 'no jobs running')" ]; do echo "waiting.."; sleep 5; done

New files
- infra/image/build.sh
- infra/image/dockerfile/c8s
- infra/image/dockerfile/c9s
- infra/image/dockerfile/c10s
- infra/image/dockerfile/fedora-latest
- infra/image/dockerfile/fedora-rawhide
- infra/image/inventory
- infra/image/system-service/fixipaip.service
- infra/image/system-service/fixipaip.sh
- infra/image/system-service/fixnet.service
- infra/image/system-service/fixnet.sh
2024-07-31 16:09:29 +02:00
Kees Bakker
c2f6a19677 README-host.md: correction of managedby_host description 2024-07-30 10:36:26 +02:00
Rafael Guterres Jeffman
0002d4c7f7 Merge pull request #1274 from t-woerner/fix_multi_user_tests
Fix multi user tests
2024-07-22 11:40:10 -03:00
Thomas Woerner
a95c222ed6 Fix multi user tests
The tests test_users_present.yml and test_users_absent.yml has been
merged into test_users_present_absent.yml to fix the independent test
order execution.

The test test_users_present_slice.yml has been renamed to
test_users_present_absent_slice.yml.

Both tests are cleaning up possible exiting entries before running the tests
and are verifying the present and absent task result.
2024-07-22 16:29:19 +02:00
Rafael Guterres Jeffman
d9a20e16c1 Merge pull request #1272 from t-woerner/add_missing_cleanup_for_test_services_present
tests/service/test_services_present.yml: Add missing cleanup
2024-07-22 11:26:45 -03:00
Rafael Guterres Jeffman
a4860f7b04 Merge pull request #1270 from t-woerner/truncate_stdout_and_stderr_in_upstream_test_log
Truncate stdout and stderr in upstream test log
2024-07-20 11:53:30 -03:00
Thomas Woerner
e71602be6e tests/service/test_services_present.yml: Add missing cleanup
The cleanup of the test services and hosts have been missing, which
could lead to a test failure.
2024-07-19 17:08:20 +02:00
Thomas Woerner
3dfa026eda Truncate stdout and stderr in upstream test log
Truncate stdout and stderr in the way that it hopefully shows all
important information. At least 15 lines of stdout (Ansible tasks) and
remaining from stderr to fill up to maxlen size.

The test log mostly only showed lines from stderr as the log was a
concatenation of stdout and stderr and only the last 2500 chars of this
have been used. This was hiding the test result from stdout and failures
have not beeen visible.
2024-07-17 10:54:30 +02:00
109 changed files with 3564 additions and 2360 deletions

View File

@@ -7,7 +7,6 @@ exclude_paths:
- .tox/
- .venv/
- .yamllint
- molecule/
- tests/azure/
- meta/runtime.yml
- requirements-docker.yml

View File

@@ -34,21 +34,6 @@ jobs:
- name: Run yaml-lint
uses: ibiqlik/action-yamllint@v3.1.1
pydocstyle:
name: Verify pydocstyle
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4.1.1
with:
fetch-depth: 1
- uses: actions/setup-python@v5.1.0
with:
python-version: "3.x"
- name: Run pydocstyle
run: |
pip install pydocstyle
pydocstyle
flake8:
name: Verify flake8
runs-on: ubuntu-latest
@@ -88,3 +73,5 @@ jobs:
fetch-depth: 1
- name: Run ShellCheck
uses: ludeeus/action-shellcheck@master
env:
SHELLCHECK_OPTS: -x

1
.gitignore vendored
View File

@@ -12,3 +12,4 @@ importer_result.json
/.venv/
tests/logs/
TEST*.xml

View File

@@ -29,10 +29,6 @@ repos:
rev: 7.0.0
hooks:
- id: flake8
- repo: https://github.com/pycqa/pydocstyle
rev: 6.3.0
hooks:
- id: pydocstyle
- repo: https://github.com/pycqa/pylint
rev: v3.2.2
hooks:
@@ -54,4 +50,7 @@ repos:
name: ShellCheck
language: system
entry: shellcheck
files: \.sh$
args: ['-x']
files: >
\.sh$
utils/sh*$

View File

@@ -44,7 +44,7 @@ Example playbook to make sure HBAC Rule login exists:
```yaml
---
- name: Playbook to handle hbacrules
hbacsvcs: ipaserver
hosts: ipaserver
become: true
tasks:
@@ -60,7 +60,7 @@ Example playbook to make sure HBAC Rule login exists with the only HBAC Service
```yaml
---
- name: Playbook to handle hbacrules
hbacsvcs: ipaserver
hosts: ipaserver
become: true
tasks:
@@ -77,7 +77,7 @@ Example playbook to make sure HBAC Service sshd is present in HBAC Rule login:
```yaml
---
- name: Playbook to handle hbacrules
hbacsvcs: ipaserver
hosts: ipaserver
become: true
tasks:
@@ -95,7 +95,7 @@ Example playbook to make sure HBAC Service sshd is absent in HBAC Rule login:
```yaml
---
- name: Playbook to handle hbacrules
hbacsvcs: ipaserver
hosts: ipaserver
become: true
tasks:
@@ -114,7 +114,7 @@ Example playbook to make sure HBAC Rule login is absent:
```yaml
---
- name: Playbook to handle hbacrules
hbacsvcs: ipaserver
hosts: ipaserver
become: true
tasks:

View File

@@ -44,7 +44,7 @@ Example playbook to make sure HBAC Service Group login exists:
```yaml
---
- name: Playbook to handle hbacsvcgroups
hbacsvcs: ipaserver
hosts: ipaserver
become: true
tasks:
@@ -60,7 +60,7 @@ Example playbook to make sure HBAC Service Group login exists with the only HBAC
```yaml
---
- name: Playbook to handle hbacsvcgroups
hbacsvcs: ipaserver
hosts: ipaserver
become: true
tasks:
@@ -77,7 +77,7 @@ Example playbook to make sure HBAC Service sshd is present in HBAC Service Group
```yaml
---
- name: Playbook to handle hbacsvcgroups
hbacsvcs: ipaserver
hosts: ipaserver
become: true
tasks:
@@ -95,7 +95,7 @@ Example playbook to make sure HBAC Service sshd is absent in HBAC Service Group
```yaml
---
- name: Playbook to handle hbacsvcgroups
hbacsvcs: ipaserver
hosts: ipaserver
become: true
tasks:
@@ -114,7 +114,7 @@ Example playbook to make sure HBAC Service Group login is absent:
```yaml
---
- name: Playbook to handle hbacsvcgroups
hbacsvcs: ipaserver
hosts: ipaserver
become: true
tasks:

View File

@@ -341,7 +341,7 @@ Variable | Description | Required
`password` \| `user_password` \| `userpassword` | Password used in bulk enrollment for absent or not enrolled hosts. | no
`random` \| `random_password` | Initiate the generation of a random password to be used in bulk enrollment for absent or not enrolled hosts. | no
`certificate` \| `usercertificate` | List of base-64 encoded host certificates | no
`managedby` \| `principalname` \| `krbprincipalname` | List of hosts that can manage this host | no
`managedby_host` | List of hosts that can manage this host | no
`principal` \| `principalname` \| `krbprincipalname` | List of principal aliases for this host | no
`allow_create_keytab_user` \| `ipaallowedtoperform_write_keys_user` | Users allowed to create a keytab of this host. | no
`allow_create_keytab_group` \| `ipaallowedtoperform_write_keys_group` | Groups allowed to create a keytab of this host. | no

View File

@@ -129,6 +129,49 @@ Example playbook to make sure Sudo Rule is absent:
state: absent
```
Example playbook to ensure multiple Sudo Rule are present using batch mode:
```yaml
---
- name: Playbook to handle sudorules
hosts: ipaserver
become: true
- name: Ensure multiple Sudo Rules are present using batch mode.
ipasudorule:
ipaadmin_password: SomeADMINpassword
sudorules:
- name: testrule1
hostmask:
- 192.168.122.1/24
- name: testrule2
hostcategory: all
```
Example playbook to ensure multiple Sudo Rule members are present using batch mode:
```yaml
---
- name: Playbook to handle sudorules
hosts: ipaserver
become: true
- name: Ensure multiple Sudo Rules are present using batch mode.
ipasudorule:
ipaadmin_password: SomeADMINpassword
action: member
sudorules:
- name: testrule1
user:
- user01
- user02
group:
- group01
- name: testrule2
hostgroup:
- hostgroup01
- hostgroup02
```
Variables
=========
@@ -139,7 +182,9 @@ Variable | Description | Required
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `cn` | The list of sudorule name strings. | yes
`name` \| `cn` | The list of sudorule name strings. | no
`sudorules` | The list of sudorule dicts. Each `sudorule` dict entry can contain sudorule variables.<br>There is one required option in the `sudorule` dict:| no
&nbsp; | `name` - The sudorule name string of the entry. | yes
`description` | The sudorule description string. | no
`usercategory` \| `usercat` | User category the rule applies to. Choices: ["all", ""] | no
`hostcategory` \| `hostcat` | Host category the rule applies to. Choices: ["all", ""] | no

View File

@@ -0,0 +1,73 @@
---
trigger:
- master
pool:
vmImage: 'ubuntu-20.04'
variables:
ansible_version: "-core >=2.16,<2.17"
ansible_latest: "-core"
ansible_minimum: "-core <2.16"
distros: "fedora-latest,c9s,fedora-rawhide"
stages:
- stage: fedora_latest_ansible_latest
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
distro: fedora-latest
ansible_version: ${{ variables.ansible_latest }}
skip_git_test: true
- stage: fedora_latest_ansible_2_15
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
distro: fedora-latest
ansible_version: ${{ variables.ansbile_minimum }}
skip_git_test: true
# Supported distros
- ${{ each distro in split(variables.distros, ',') }}:
- stage: ${{ replace(distro, '-', '_') }}_ansible_2_16
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
distro: ${{ distro }}
ansible_version: ${{ variables.ansible_version }}
skip_git_test: true
test_galaxy: false
# Galaxy on Fedora
- stage: galaxy_fedora_latest_ansible_2_16
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
distro: fedora-latest
ansible_version: ${{ variables.ansible_version }}
skip_git_test: true
test_galaxy: true
# CentOS 8 Stream, latest supported Ansible version.
- stage: c8s_ansible_2_16
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
distro: c8s
ansible_version: "-core <2.17"
skip_git_test: true

View File

@@ -0,0 +1,35 @@
---
schedules:
- cron: "0 0 * * 0"
displayName: Weekly Sunday midnight build
branches:
include:
- master
always: true
trigger: none
pool:
vmImage: 'ubuntu-24.04'
variables: { distros: "fedora-latest,fedora-rawhide,c9s" }
stages:
- ${{ each distro in split(variables.distros, ',') }}:
- stage: build_${{ join('_', split(distro, '-')) }}
dependsOn: []
jobs:
- template: templates/build_container.yml
parameters:
distro: ${{ distro }}
# Special case for CentOS 8 Stream
- stage: CentOS_8_Stream
dependsOn: []
jobs:
- template: templates/build_container.yml
parameters:
distro: c8s
# ansible-core 2.17+ cannot be used to deploy on CentOS 8 Stream.
ansible_core_version: "<2.17"

79
infra/azure/nightly.yml Normal file
View File

@@ -0,0 +1,79 @@
---
schedules:
- cron: "0 19 * * *"
displayName: Nightly Builds
branches:
include:
- master
always: true
trigger: none
pool:
vmImage: 'ubuntu-20.04'
variables:
# We need to have two sets, as c8s is not supported by all ansible versions
recent_distros: "fedora-latest,fedora-rawhide,c9s"
distros: "fedora-latest,fedora-rawhide,c9s,c8s"
ansible_latest: "-core"
ansible_minimum: "-core <2.16"
ansible_version: "-core >=2.16,<2.17"
stages:
# Minimum ansible
- ${{ each distro in split(variables.distros, ',') }}:
- stage: ${{ replace(distro, '-', '_') }}_ansible_2_15
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
distro: fedora-latest
ansible_version: ${{ variables.ansible_minimum }}
skip_git_test: true
test_galaxy: false
# Latest ansible
- ${{ each distro in split(variables.recent_distros, ',') }}:
- stage: ${{ replace(distro, '-', '_') }}_ansible_latest
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
distro: ${{ distro }}
ansible_version: ${{ variables.ansible_latest }}
skip_git_test: true
test_galaxy: false
# Selected ansible-core version
- ${{ each distro in split(variables.distros, ',') }}:
- stage: ${{ replace(distro, '-', '_') }}_ansible_2_16
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
distro: ${{ distro }}
ansible_version: ${{ variables.ansible_version }}
skip_git_test: true
test_galaxy: false
# Galaxy collection with selected ansible-core version
- ${{ each distro in split(variables.distros, ',') }}:
- stage: galaxy_${{ replace(distro, '-', '_') }}_asible_2_16
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
distro: ${{ distro }}
ansible_version: ${{ variables.ansible_version }}
skip_git_test: true
test_galaxy: true

View File

@@ -0,0 +1,39 @@
---
trigger:
- master
pool:
vmImage: 'ubuntu-20.04'
variables:
distros: "fedora-latest,c9s,c8s,fedora-rawhide"
ansible_version: "-core >=2.15,<2.16"
stages:
# Test with repository in all distros
- ${{ each distro in split(variables.distros, ',') }}:
- stage: ${{ replace(distro, '-', '_') }}_ansible_2_16
dependsOn: []
jobs:
- template: templates/run_tests.yml
parameters:
build_number: $(Build.BuildNumber)
distro: ${{ distro }}
ansible_version: ${{ variables.ansible_version }}
skip_git_test: false
test_galaxy: false
# Galaxy on Fedora
- stage: galaxy_fedora_latest_ansible_2_16
dependsOn: []
jobs:
- template: templates/run_tests.yml
parameters:
build_number: $(Build.BuildNumber)
distro: fedora-latest
ansible_version: ${{ variables.ansible_version }}
skip_git_test: false
test_galaxy: true

View File

@@ -159,7 +159,7 @@ def map_test_module_sources(base):
"""Create a map of 'test-modules' to 'plugin-sources', from 'base'."""
# Find root directory of playbook tests.
script_dir = os.path.dirname(__file__)
test_root = os.path.realpath(os.path.join(script_dir, f"../{base}"))
test_root = os.path.realpath(os.path.join(script_dir, f"../../../{base}"))
# create modules:source_files map
_result = {}
for test_module in [d for d in os.scandir(test_root) if d.is_dir()]:
@@ -170,7 +170,7 @@ def map_test_module_sources(base):
def usage(err=0):
print("filter_plugins.py [-h|--help] [-p|--pytest] PY_SRC...")
print("get_test_modules.py [-h|--help] [-p|--pytest] PY_SRC...")
print(
"""
Print a comma-separated list of modules that should be tested if

View File

@@ -0,0 +1,67 @@
#!/bin/bash -eu
# This file shoud be source'd (. set_test_modules) rather than executed.
#
# Set SKIP_GIT_TEST="True" or use -a to prevent git modification comparison.
#
RED="\033[31;1m"
RST="\033[0m"
die() {
echo -e "${RED}${*}${RST}" >&2
}
BASEDIR="$(readlink -f "$(dirname "${BASH_SOURCE[0]}")")"
TOPDIR="$(readlink -f "${BASEDIR}/../../..")"
[ -n "$(command -v python3)" ] && python="$(command -v python3)" || python="$(command -v python2)"
pushd "${TOPDIR}" >/dev/null 2>&1 || die "Failed to change directory."
SKIP_GIT_TEST=${SKIP_GIT_TEST:-"False"}
while getopts ":a" opt
do
case "${opt}" in
a) SKIP_GIT_TEST="True" ;;
*) ;; # ignore other options
esac
done
files_list=$(mktemp)
enabled_modules="None"
enabled_tests="None"
if [ "${SKIP_GIT_TEST}" != "True" ]
then
remote="$(basename "$(mktemp -u remote_XXXXXX)")"
git remote add "${remote}" https://github.com/freeipa/ansible-freeipa
git fetch --prune --no-tags --quiet "${remote}"
git diff "${remote}/master" --name-only > "${files_list}"
git remote remove "${remote}"
# shellcheck disable=SC2046
enabled_modules="$(${python} "${BASEDIR}/get_test_modules.py" $(cat "${files_list}"))"
[ -z "${enabled_modules}" ] && enabled_modules="None"
# Get individual tests that should be executed
mapfile -t tests < <(sed -n 's#.*/\(test_[^/]*\).yml#\1#p' "${files_list}" | tr -d " ")
[ ${#tests[@]} -gt 0 ] && enabled_tests=$(IFS=, ; echo "${tests[*]}")
[ -z "${enabled_tests}" ] && enabled_tests="None"
[ -n "${enabled_tests}" ] && IPA_ENABLED_TESTS="${enabled_tests},${IPA_ENABLED_TESTS}"
[ -n "${enabled_modules}" ] && IPA_ENABLED_MODULES="${enabled_modules},${IPA_ENABLED_MODULES}"
rm -f "${files_list}"
fi
# Get all modules that should have tests executed
export IPA_ENABLED_MODULES
export IPA_ENABLED_TESTS
echo "IPA_ENABLED_MODULES = [${IPA_ENABLED_MODULES}]"
echo "IPA_ENABLED_TESTS = [${IPA_ENABLED_TESTS}]"
popd >/dev/null 2>&1 || die "Failed to change back to original directory."

View File

@@ -0,0 +1,45 @@
---
parameters:
- name: distro
type: string
- name: python_version
type: string
default: 3.x
- name: ansible_core_version
default: ""
jobs:
- job: BuildTestImage_${{ join('_', split(parameters.distro, '-')) }}
displayName: Build ${{ parameters.distro }} test container
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '${{ parameters.python_version }}'
- script: python -m pip install --upgrade pip "ansible-core${{ parameters.ansible_core_version }}"
retryCountOnTaskFailure: 5
displayName: Install tools
- script: ansible-galaxy collection install containers.podman
displayName: Install Ansible Galaxy collections
- script: infra/image/build.sh -p -s ${{ parameters.distro }}
displayName: Build ${{ parameters.distro }} base image
env:
ANSIBLE_ROLES_PATH: "${PWD}/roles"
ANSIBLE_LIBRARY: "${PWD}/plugins/modules"
ANSIBLE_MODULE_UTILS: "${PWD}/plugins/module_utils"
- script: podman login -u="$QUAY_ROBOT_USERNAME" -p="$QUAY_ROBOT_TOKEN" quay.io
displayName: Registry login
env:
# Secrets needs to be mapped as env vars to work properly
QUAY_ROBOT_TOKEN: $(QUAY_ROBOT_TOKEN)
- script: |
podman push quay.io/ansible-freeipa/upstream-tests:${{parameters.distro}}-base quay.io/ansible-freeipa/upstream-tests:${{ parameters.distro }}-base
displayName: Push base image
- script: |
podman push quay.io/ansible-freeipa/upstream-tests:${{ parameters.distro }}-server quay.io/ansible-freeipa/upstream-tests:${{ parameters.distro }}-server
displayName: Push server image

View File

@@ -0,0 +1,30 @@
---
parameters:
- name: distro
type: string
default: fedora-latest
- name: build_number
type: string
- name: ansible_version
type: string
default: ""
- name: skip_git_test
type: boolean
default: false
- name: test_galaxy
type: boolean
default: false
jobs:
- ${{ each group in split('1,2,3', ',') }}:
- template: run_tests.yml
parameters:
group_number: ${{ group }}
number_of_groups: 3
build_number: ${{ parameters.build_number }}
distro: ${{ parameters.distro }}
ansible_version: ${{ parameters.ansible_version }}
python_version: '< 3.12'
skip_git_test: ${{ parameters.skip_git_test }}
test_galaxy: ${{ parameters.test_galaxy }}

View File

@@ -0,0 +1,30 @@
---
parameters:
- name: distro
type: string
default: fedora-latest
- name: ansible_version
type: string
default: ""
- name: python_version
type: string
default: 3.x
- name: build_number
type: string
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '${{ parameters.python_version }}'
- script: |
pip install "ansible${{ parameters.ansible_version }}" -r requirements-tests.txt
retryCountOnTaskFailure: 5
displayName: Install test dependencies
- script: ansible-galaxy collection install -r requirements-podman.yml
retryCountOnTaskFailure: 5
displayName: Install Ansible collections
- script: infra/image/start.sh ${{ parameters.distro }}-server
displayName: Setup target container for ${{ parameters.distro }}

View File

@@ -0,0 +1,98 @@
---
parameters:
- name: group_number
type: number
default: 1
- name: number_of_groups
type: number
default: 1
- name: distro
type: string
default: fedora-latest
- name: ansible_version
type: string
default: ""
- name: python_version
type: string
default: 3.x
- name: build_number
type: string
- name: skip_git_test
type: boolean
default: true
- name: test_type
type: string
default: "playbook"
- name: test_galaxy
type: boolean
default: false
jobs:
- job: Test_Group${{ parameters.group_number }}
displayName: Run playbook tests ${{ parameters.distro }} (${{ parameters.group_number }}/${{ parameters.number_of_groups }})
timeoutInMinutes: 360
variables:
- template: variables.yaml
- template: variables_${{ parameters.distro }}.yaml
steps:
- template: prepare_environment.yaml
parameters:
build_number: ${{ parameters.build_number }}
distro: ${{ parameters.distro }}
ansible_version: ${{ parameters.ansible_version }}
python_version: ${{ parameters.python_version }}
- bash: echo "##vso[task.setvariable variable=TOPDIR]${PWD}"
displayName: Set repo rootdir
- script: |
. "${TOPDIR}/infra/azure/scripts/set_test_modules"
python3 utils/check_test_configuration.py ${{ parameters.distro }}
displayName: Check test configuration
env:
SKIP_GIT_TEST: ${{ parameters.skip_git_test }}
- script: |
git fetch --unshallow
utils/build-galaxy-release.sh -i
retryCountOnTaskFailure: 5
displayName: Build Galaxy release
condition: ${{ parameters.test_galaxy }}
- script: |
echo "PWD: ${PWD}"
echo "TOPDIR: ${TOPDIR}"
echo "ROLES: ${ANSIBLE_ROLES_PATH}"
echo "LIBRARY: ${ANSIBLE_LIBRARY}"
echo "MODULE_UTILS: ${ANSIBLE_MODULE_UTILS}"
. "${TOPDIR}/infra/azure/scripts/set_test_modules"
[ "${{ parameters.test_galaxy }}" == "True" ] && cd ~/.ansible/collections/ansible_collections/freeipa/ansible_freeipa
pytest \
-m "${{ parameters.test_type }}" \
--verbose \
--color=yes \
--splits=${{ parameters.number_of_groups }} \
--group=${{ parameters.group_number }} \
--randomly-seed=$(date "+%Y%m%d") \
--suppress-no-test-exit-code \
--junit-xml=TEST-results-pr-check.xml
displayName: Run playbook tests
env:
SKIP_GIT_TEST: ${{ parameters.skip_git_test }}
${{ if not(parameters.test_galaxy) }}:
ANSIBLE_ROLES_PATH: "${PWD}/roles"
ANSIBLE_LIBRARY: "${PWD}/plugins"
ANSIBLE_MODULE_UTILS: "${PWD}/plugins/module_utils"
IPA_SERVER_HOST: ansible-freeipa-tests
RUN_TESTS_IN_DOCKER: podman
IPA_DISABLED_MODULES: ${{ variables.ipa_disabled_modules }}
IPA_DISABLED_TESTS: ${{ variables.ipa_disabled_tests }}
IPA_ENABLED_MODULES: ${{ variables.ipa_enabled_modules }}
IPA_ENABLED_TESTS: ${{ variables.ipa_enabled_tests }}
IPA_VERBOSITY: "-vvv"
- task: PublishTestResults@2
inputs:
mergeTestResults: true
testRunTitle: PlaybookTests-Build${{ parameters.build_number }}
condition: succeededOrFailed()

View File

@@ -0,0 +1,15 @@
[ipaserver]
ansible-freeipa-image-builder ansible_connection=podman
[ipaserver:vars]
ipaadmin_password=SomeADMINpassword
ipadm_password=SomeDMpassword
ipaserver_domain=test.local
ipaserver_realm=TEST.LOCAL
ipaserver_setup_dns=true
ipaserver_auto_forwarders=true
ipaserver_no_dnssec_validation=true
ipaserver_auto_reverse=true
ipaserver_setup_kra=true
ipaserver_setup_firewalld=false
ipaclient_no_ntp=true

135
infra/image/build.sh Executable file
View File

@@ -0,0 +1,135 @@
#!/bin/bash -eu
BASEDIR="$(readlink -f "$(dirname "$0")")"
TOPDIR="$(readlink -f "${BASEDIR}/../..")"
# shellcheck disable=SC1091
. "${BASEDIR}/shcontainer"
# shellcheck disable=SC1091
. "${TOPDIR}/utils/shfun"
valid_distro() {
find "${BASEDIR}/dockerfile" -type f -printf "%f\n" | tr "\n" " "
}
usage() {
local prog="${0##*/}"
cat << EOF
usage: ${prog} [-h] [-p] [-n HOSTNAME] [-s] distro
${prog} build a container image to test ansible-freeipa.
EOF
}
help() {
cat << EOF
positional arguments:
distro The base distro to build the test container.
Availble distros: $(valid_distro)
optional arguments:
-n HOSTNAME Container hostname
-p Give extended privileges to the container
-s Deploy IPA server
EOF
}
name="ansible-freeipa-image-builder"
hostname="ipaserver.test.local"
cpus="2"
memory="3g"
quayname="quay.io/ansible-freeipa/upstream-tests"
deploy_server="N"
privileged=""
while getopts ":hn:ps" option
do
case "${option}" in
h) help && exit 0 ;;
n) hostname="${OPTARG}" ;;
p) privileged="privileged" ;;
s) deploy_server="Y" ;;
*) die -u "Invalid option: ${option}" ;;
esac
done
shift $((OPTIND - 1))
distro=${1:-}
[ -n "${distro}" ] || die "Distro needs to be given.\nUse one of: $(valid_distro)"
[ -f "${BASEDIR}/dockerfile/${distro}" ] \
|| die "${distro} is not a valid distro target.\nUse one of: $(valid_distro)"
container_check
if [ "${deploy_server}" == "Y" ]
then
[ -n "$(command -v "ansible-playbook")" ] || die "ansible-playbook is required to install FreeIPA."
deploy_playbook="${TOPDIR}/playbooks/install-server.yml"
[ -f "${deploy_playbook}" ] || die "Can't find playbook '${deploy_playbook}'"
inventory_file="${BASEDIR}/build-inventory"
[ -f "${inventory_file}" ] || die "Can't find inventory '${inventory_file}'"
fi
container_state=$(container_get_state "${name}")
tag="${distro}-base"
server_tag="${distro}-server"
container_remove_image_if_exists "${tag}"
[ "${deploy_server}" == "Y" ] && \
container_remove_image_if_exists "${server_tag}"
container_build "${tag}" "${BASEDIR}/dockerfile/${distro}" "${BASEDIR}"
container_create "${name}" "${tag}" \
"hostname=${hostname}" \
"memory=${memory}" \
"cpus=${cpus}" \
"${privileged}"
container_commit "${name}" "${quayname}:${tag}"
if [ "${deploy_server}" == "Y" ]
then
deployed=false
# Set path to ansible-freeipa roles
[ -z "${ANSIBLE_ROLES_PATH:-""}" ] && export ANSIBLE_ROLES_PATH="${TOPDIR}/roles"
# Install collection containers.podman if not available
if [ -z "$(ansible-galaxy collection list containers.podman)" ]
then
tmpdir="$(mktemp -d)"
export ANSIBLE_COLLECTIONS_PATH="${tmpdir}"
ansible-galaxy collection install -p "${tmpdir}" containers.podman
fi
[ "${container_state}" != "running" ] && container_start "${name}"
container_wait_for_journald "${name}"
log info "= Deploying IPA ="
if ansible-playbook -u root -i "${inventory_file}" "${deploy_playbook}"
then
deployed=true
fi
echo
if $deployed; then
log info "= Enabling services ="
container_exec "${name}" systemctl enable fixnet
container_exec "${name}" systemctl enable fixipaip
echo
fi
container_stop "${name}"
$deployed || die "Deployment failed"
container_commit "${name}" "${quayname}:${server_tag}"
fi
log info "= DONE: Image created. ="

View File

@@ -0,0 +1,38 @@
FROM quay.io/centos/centos:stream10-development
ENV container=podman
RUN rm -fv /var/cache/dnf/metadata_lock.pid; \
dnf makecache; \
dnf --assumeyes install \
/usr/bin/dnf-3 \
sudo \
bash \
systemd \
procps-ng \
iproute; \
rm -rf /var/cache/dnf/;
RUN (cd /lib/systemd/system/; \
if [ -e dbus-broker.service ] && [ ! -e dbus.service ]; then \
ln -s dbus-broker.service dbus.service; \
fi \
)
COPY system-service/container-ipa.target /lib/systemd/system/
RUN systemctl set-default container-ipa.target
RUN (cd /etc/systemd/system/; \
rm -rf multi-user.target.wants \
&& mkdir container-ipa.target.wants \
&& ln -s container-ipa.target.wants multi-user.target.wants \
)
COPY system-service/fixnet.sh /root/
COPY system-service/fixipaip.sh /root/
COPY system-service/fixnet.service /etc/systemd/system/
COPY system-service/fixipaip.service /etc/systemd/system/
RUN chmod +x /root/fixnet.sh /root/fixipaip.sh
STOPSIGNAL RTMIN+3
VOLUME ["/sys/fs/cgroup"]
CMD ["/usr/sbin/init"]

View File

@@ -0,0 +1,43 @@
FROM quay.io/centos/centos:stream8
ENV container=podman
RUN rm -fv /var/cache/dnf/metadata_lock.pid; \
sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/*.repo; \
sed -i s/^#.*baseurl=http/baseurl=http/g /etc/yum.repos.d/*.repo; \
sed -i s/^mirrorlist=http/#mirrorlist=http/g /etc/yum.repos.d/*.repo; \
dnf makecache; \
dnf --assumeyes install \
/usr/bin/dnf-3 \
sudo \
bash \
systemd \
procps-ng \
iproute; \
dnf clean all; \
rm -rf /var/cache/dnf/;
RUN (cd /lib/systemd/system/; \
if [ -e dbus-broker.service ] && [ ! -e dbus.service ]; then \
ln -s dbus-broker.service dbus.service; \
fi \
)
COPY system-service/container-ipa.target /lib/systemd/system/
RUN systemctl set-default container-ipa.target
RUN (cd /etc/systemd/system/; \
rm -rf multi-user.target.wants \
&& mkdir container-ipa.target.wants \
&& ln -s container-ipa.target.wants multi-user.target.wants \
)
COPY system-service/fixnet.sh /root/
COPY system-service/fixipaip.sh /root/
COPY system-service/fixnet.service /etc/systemd/system/
COPY system-service/fixipaip.service /etc/systemd/system/
RUN chmod +x /root/fixnet.sh /root/fixipaip.sh
STOPSIGNAL RTMIN+3
VOLUME ["/sys/fs/cgroup"]
CMD ["/usr/sbin/init"]

View File

@@ -0,0 +1,38 @@
FROM quay.io/centos/centos:stream9
ENV container=podman
RUN rm -fv /var/cache/dnf/metadata_lock.pid; \
dnf makecache; \
dnf --assumeyes install \
/usr/bin/dnf-3 \
sudo \
bash \
systemd \
procps-ng \
iproute; \
rm -rf /var/cache/dnf/;
RUN (cd /lib/systemd/system/; \
if [ -e dbus-broker.service ] && [ ! -e dbus.service ]; then \
ln -s dbus-broker.service dbus.service; \
fi \
)
COPY system-service/container-ipa.target /lib/systemd/system/
RUN systemctl set-default container-ipa.target
RUN (cd /etc/systemd/system/; \
rm -rf multi-user.target.wants \
&& mkdir container-ipa.target.wants \
&& ln -s container-ipa.target.wants multi-user.target.wants \
)
COPY system-service/fixnet.sh /root/
COPY system-service/fixipaip.sh /root/
COPY system-service/fixnet.service /etc/systemd/system/
COPY system-service/fixipaip.service /etc/systemd/system/
RUN chmod +x /root/fixnet.sh /root/fixipaip.sh
STOPSIGNAL RTMIN+3
VOLUME ["/sys/fs/cgroup"]
CMD ["/usr/sbin/init"]

View File

@@ -0,0 +1,41 @@
FROM fedora:latest
ENV container=podman
RUN rm -fv /var/cache/dnf/metadata_lock.pid; \
dnf makecache; \
dnf --assumeyes install \
/usr/bin/python3 \
/usr/bin/python3-config \
python3-libdnf5 \
sudo \
bash \
systemd \
procps-ng \
iproute; \
dnf clean all; \
rm -rf /var/cache/dnf/;
RUN (cd /lib/systemd/system/; \
if [ -e dbus-broker.service ] && [ ! -e dbus.service ]; then \
ln -s dbus-broker.service dbus.service; \
fi \
)
COPY system-service/container-ipa.target /lib/systemd/system/
RUN systemctl set-default container-ipa.target
RUN (cd /etc/systemd/system/; \
rm -rf multi-user.target.wants \
&& mkdir container-ipa.target.wants \
&& ln -s container-ipa.target.wants multi-user.target.wants \
)
COPY system-service/fixnet.sh /root/
COPY system-service/fixipaip.sh /root/
COPY system-service/fixnet.service /etc/systemd/system/
COPY system-service/fixipaip.service /etc/systemd/system/
RUN chmod +x /root/fixnet.sh /root/fixipaip.sh
STOPSIGNAL RTMIN+3
VOLUME ["/sys/fs/cgroup"]
CMD ["/usr/sbin/init"]

View File

@@ -0,0 +1,41 @@
FROM fedora:rawhide
ENV container=podman
RUN rm -fv /var/cache/dnf/metadata_lock.pid; \
dnf makecache; \
dnf --assumeyes install \
/usr/bin/python3 \
/usr/bin/python3-config \
python3-libdnf5 \
sudo \
bash \
systemd \
procps-ng \
iproute; \
dnf clean all; \
rm -rf /var/cache/dnf/;
RUN (cd /lib/systemd/system/; \
if [ -e dbus-broker.service ] && [ ! -e dbus.service ]; then \
ln -s dbus-broker.service dbus.service; \
fi \
)
COPY system-service/container-ipa.target /lib/systemd/system/
RUN systemctl set-default container-ipa.target
RUN (cd /etc/systemd/system/; \
rm -rf multi-user.target.wants \
&& mkdir container-ipa.target.wants \
&& ln -s container-ipa.target.wants multi-user.target.wants \
)
COPY system-service/fixnet.sh /root/
COPY system-service/fixipaip.sh /root/
COPY system-service/fixnet.service /etc/systemd/system/
COPY system-service/fixipaip.service /etc/systemd/system/
RUN chmod +x /root/fixnet.sh /root/fixipaip.sh
STOPSIGNAL RTMIN+3
VOLUME ["/sys/fs/cgroup"]
CMD ["/usr/sbin/init"]

6
infra/image/inventory Normal file
View File

@@ -0,0 +1,6 @@
[ipaserver]
ansible-freeipa-tests ansible_connection=podman
[ipaserver:vars]
ipaadmin_password=SomeADMINpassword
ipadm_password=SomeDMpassword

177
infra/image/shcontainer Normal file
View File

@@ -0,0 +1,177 @@
#!/bin/bash -eu
# This file is meant to be source'd by other scripts
SCRIPTDIR="$(dirname -- "$(readlink -f "${BASH_SOURCE[0]}")")"
TOPDIR="$(readlink -f "${SCRIPTDIR}/../..")"
. "${TOPDIR}/utils/shfun"
container_create() {
local name=${1}
local image=${2}
shift 2
declare -a extra_opts=()
for opt in "$@"
do
[ -z "${opt}" ] && continue
case "${opt}" in
hostname=*) extra_opts+=("--${opt}") ;;
cpus=*) extra_opts+=("--${opt}") ;;
memory=*) extra_opts+=("--${opt}") ;;
privileged) extra_opts+=("--${opt}") ;;
*) log error "container_create: Invalid option: ${opt}" ;;
esac
done
# ensure default values are set
[[ " ${extra_opts[*]} " =~ " --cpus=" ]] || extra_opts+=("--cpus=2")
[[ " ${extra_opts[*]} " =~ " --hostname=" ]] \
|| extra_opts+=("--hostname=ipaserver.test.local")
log info "= Creating ${name} ="
podman create \
--security-opt label=disable \
--network bridge:interface_name=eth0 \
--systemd true \
--name "${name}" \
--memory-swap -1 \
--no-hosts \
--replace \
"${extra_opts[@]}" \
"${image}"
echo
}
container_start() {
local name="${1}"
log info "= Starting ${name} ="
podman start "${name}"
echo
}
container_stop() {
local name="${1}"
log info "= Stopping ${name} ="
podman stop "${name}"
echo
}
container_wait_for_journald() {
local name=${1}
log info "= Waiting till systemd-journald is running ="
max=20
wait=2
count=0
while ! podman exec "${name}" ps -x | grep -q "systemd-journald"
do
if [ $count -ge $max ]; then
die "Timeout: systemd-journald is not starting up"
fi
count=$((count+1))
log info "Waiting ${wait} seconds .."
sleep ${wait}
done
log info "done"
echo
}
container_wait_up() {
local name="${1}"
log info "= Waiting till all services are started ="
max=20
wait=15
count=0
while podman exec "${name}" systemctl list-jobs | \
grep -qvi "no jobs running"
do
if [ $count -ge $max ]; then
die "Timeout: Services are not starting up"
fi
count=$((count+1))
log info "Waiting ${wait} seconds .."
sleep ${wait}
done
log info "done"
echo
}
container_build() {
local tag="${1}"
local file="${2}"
local dir="${3}"
log info "= Building ${tag} ="
podman build -t "${tag}" -f "${file}" "${dir}"
echo
}
container_commit() {
local name="${1}"
local image="${2}"
log info "= Committing \"${image}\" ="
podman commit "${name}" "${image}"
echo
}
container_exec() {
local name="${1}"
shift 1
# "@Q" is only needed for the log output, the exec command is properly
# working without also for args containing spaces.
log info "= Executing \"${*@Q}\" ="
podman exec -t "${name}" "${@}"
echo
}
container_remove_image_if_exists()
{
# In older (as in Ubuntu 22.04) podman versions,
# 'podman image rm --force' fails if the image
# does not exist.
local tag_to_remove="${1}"
if podman image exists "${tag_to_remove}"
then
log info "= Cleanup ${tag_to_remove} ="
podman image rm "${tag_to_remove}" --force
echo
fi
}
container_get_state()
{
local name="${1}"
state=$(podman ps -q --all --format "{{.State}}" --filter "name=${name}")
echo "${state}"
}
container_pull() {
local source="${1}"
image=$(podman pull "${source}")
echo "${image}"
}
container_image_list() {
local source="${1}"
# Append "$" for an exact match if the source does not end with ":" to
# search for the repo only.
if [[ ${source} != *: ]]; then
source="${source}$"
fi
image=$(podman image list --format "{{ .Repository }}:{{ .Tag }}" | \
grep "^${source}")
echo "${image}"
}
container_check() {
[ -n "$(command -v "podman")" ] || die "podman is required."
}

95
infra/image/start.sh Executable file
View File

@@ -0,0 +1,95 @@
#!/bin/bash -eu
BASEDIR="$(readlink -f "$(dirname "$0")")"
TOPDIR="$(readlink -f "${BASEDIR}/../..")"
# shellcheck disable=SC1091
. "${BASEDIR}/shcontainer"
# shellcheck disable=SC1091
. "${TOPDIR}/utils/shfun"
usage() {
local prog="${0##*/}"
cat << EOF
usage: ${prog} [-h] [-l] [-n HOSTNAME ] image
${prog} start a prebuilt ansible-freeipa test container image.
EOF
}
help() {
cat << EOF
positional arguments:
image The image to start, leave empty to get list of images
optional arguments:
-h Show this message
-l Try to use local image first, if not found download.
-n HOSTNAME Set container hostname
NOTE:
- The hostname must be the same as the hostname of the container
when FreeIPA was deployed. Use only if you built the image and
defined its hostname.
EOF
}
list_images() {
local quay_api="https://quay.io/api/v1/repository/ansible-freeipa/upstream-tests/tag"
log info "Available images on quay:"
curl --silent -L "${quay_api}" | jq '.tags[]|.name' | tr -d '"'| sort | uniq | sed "s/.*/ &/"
echo
log info "Local images (use -l):"
local_image=$(container_image_list "${repo}:")
echo "${local_image}" | sed -e "s/.*://" | sed "s/.*/ &/"
echo
}
repo="quay.io/ansible-freeipa/upstream-tests"
name="ansible-freeipa-tests"
hostname="ipaserver.test.local"
try_local_first="N"
while getopts ":hln:" option
do
case "${option}" in
h) help && exit 0 ;;
l) try_local_first="Y" ;;
n) hostname="${OPTARG}" ;;
*) die -u "Invalid option: ${option}" ;;
esac
done
shift $((OPTIND - 1))
image=${1:-}
container_check
if [ -z "${image}" ]; then
list_images
exit 0
fi
local_image=
if [ "${try_local_first}" == "Y" ]; then
log info "= Trying to use local image first ="
local_image=$(container_image_list "${repo}:${image}")
[ -n "${local_image}" ] && log info "Found ${local_image}"
echo
fi
if [ -z "${local_image}" ]; then
log info "= Downloading from quay ="
local_image=$(container_pull "${repo}:${image}")
echo
fi
[ -z "${local_image}" ] && die "Image '${image}' is not valid"
container_create "${name}" "${local_image}" "hostname=${hostname}"
container_start "${name}"
container_wait_for_journald "${name}"
container_wait_up "${name}"
log info "Container ${name} is ready to be used."

View File

@@ -0,0 +1,6 @@
[Unit]
Description=Minimal target for containerized FreeIPA server
DefaultDependencies=false
AllowIsolate=yes
Requires=systemd-tmpfiles-setup.service systemd-journald.service dbus.service
After=systemd-tmpfiles-setup.service systemd-journald.service dbus.service

View File

@@ -0,0 +1,12 @@
[Unit]
Description=Fix IPA server IP in IPA Server
After=ipa.service
[Service]
Type=oneshot
ExecStart=/root/fixipaip.sh
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=default.target

View File

@@ -0,0 +1,85 @@
#!/bin/bash -eu
function valid_fqdn()
{
local name="${1}"
[[ "${name}" =~ [[:space:]] ]] && return 1
[[ "${name}" =~ \. ]] || return 1
[[ "${name}" =~ \.\. ]] && return 1
for i in ${name//./ }; do
[[ "${i}" =~ ^[a-z0-9_/]+$ ]] || return 1
done
[[ "${name}" == "localhost.localdomain" ]] && return 1
return 0
}
function valid_ipv4()
{
local ip="${1}"
local rematch="^([0-9]{1,3}\.){3}[0-9]{1,3}$"
[[ "${ip}" =~ ${rematch} ]] || return 1
for i in ${ip//./ }; do
[[ ${i} -le 255 ]] || return 1
done
return 0
}
HOSTNAME=$(hostname)
IP=$(hostname -I | cut -d " " -f 1)
export KRB5CCNAME=ansible_freeipa_cache
if [ -z "${HOSTNAME}" ] || ! valid_fqdn "${HOSTNAME}" ; then
echo "ERROR: Got invalid hostname: '${HOSTNAME}'"
exit 1
fi
if [ -z "${IP}" ] || ! valid_ipv4 "${IP}" ; then
echo "ERROR: Got invalid IPv4 address: '${IP}'"
exit 1
fi
PTR=$(echo "${IP}" | awk -F"." '{print $4}')
if [ -z "${PTR}" ] || [ -n "${PTR//[0-9]}" ]; then
echo "ERROR: Failed to get PTR from IPv4 address: '${PTR}'"
exit 1
fi
FORWARDER=$(grep -s -m 1 ^nameserver /etc/resolv.conf.fixnet | cut -d" " -f 2)
if [ -z "${FORWARDER}" ] || [ "${FORWARDER}" == "127.0.0.1" ]; then
FORWARDER="8.8.8.8"
fi
echo "Fix IPA:"
echo " HOSTNAME: '${HOSTNAME}'"
echo " IP: '${IP}'"
echo " PTR: '${PTR}'"
echo " FORWARDER: '${FORWARDER}'"
ZONES=$(ipa -e in_server=true dnszone-find --name-from-ip="${HOSTNAME}." \
--raw --pkey-only | grep "idnsname:" | awk -F": " '{print $2}')
for zone in ${ZONES}; do
echo
if [[ "${zone}" == *".in-addr.arpa."* ]]; then
echo "Fixing reverse zone ${zone}:"
OLD_PTR=$(ipa -e in_server=true dnsrecord-find "${zone}" \
--ptr-rec="${HOSTNAME}." --raw | grep "idnsname:" | \
awk -F": " '{print $2}')
if [ -z "${OLD_PTR}" ] || [ -n "${OLD_PTR//[0-9]}" ]; then
echo "ERROR: Failed to get old PTR from '${zone}': '${OLD_PTR}'"
else
ipa -e in_server=true dnsrecord-mod "${zone}" "${OLD_PTR}" \
--ptr-rec="${HOSTNAME}." --rename="${PTR}" || true
fi
else
echo "Fixing forward zone ${zone}:"
ipa -e in_server=true dnsrecord-mod test.local "${HOSTNAME%%.*}" \
--a-rec="$IP" || true
ipa -e in_server=true dnsrecord-mod test.local ipa-ca \
--a-rec="$IP" || true
fi
done
ipa -e in_server=true dnsserver-mod "${HOSTNAME}" \
--forwarder="${FORWARDER}" || true
exit 0

View File

@@ -0,0 +1,14 @@
[Unit]
Description=Fix server IP in IPA Server
Wants=network.target
After=network.target
Before=ipa.service
[Service]
Type=oneshot
ExecStart=/root/fixnet.sh
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=ipa.service

View File

@@ -0,0 +1,66 @@
#!/bin/bash -eu
function valid_fqdn()
{
local name="${1}"
[[ "${name}" =~ [[:space:]] ]] && return 1
[[ "${name}" =~ \. ]] || return 1
[[ "${name}" =~ \.\. ]] && return 1
for i in ${name//./ }; do
[[ "${i}" =~ ^[a-z0-9_/]+$ ]] || return 1
done
[[ "${name}" == "localhost.localdomain" ]] && return 1
return 0
}
function valid_ipv4()
{
local ip="${1}"
local rematch="^([0-9]{1,3}\.){3}[0-9]{1,3}$"
[[ "${ip}" =~ ${rematch} ]] || return 1
for i in ${ip//./ }; do
[[ ${i} -le 255 ]] || return 1
done
return 0
}
HOSTNAME=$(hostname)
IP=$(hostname -I | cut -d " " -f 1)
if [ -z "${HOSTNAME}" ] || ! valid_fqdn "${HOSTNAME}" ; then
echo "ERROR: Failed to retrieve hostname."
exit 1
fi
if [ -z "${IP}" ] || ! valid_ipv4 "${IP}" ; then
echo "ERROR: Got invalid IPv4 address: '${IP}'"
exit 1
fi
echo "Fix NET:"
echo " HOSTNAME: '${HOSTNAME}'"
echo " IP: '${IP}'"
echo
if grep -qE "^[^(#\s*)][0-9\.]+\s$HOSTNAME(\s|$)" /etc/hosts
then
sed -i.bak -e "s/.*${HOSTNAME}/${IP}\t${HOSTNAME}/" /etc/hosts
else
echo -e "$IP\t${HOSTNAME} ${HOSTNAME%%.*}" >> /etc/hosts
fi
cp -a /etc/resolv.conf /etc/resolv.conf.fixnet
cat > /etc/resolv.conf <<EOF
search ${HOSTNAME#*.}
nameserver 127.0.0.1
EOF
echo "/etc/hosts:"
cat "/etc/hosts"
echo
echo "/etc/resolv.conf:"
cat "/etc/resolv.conf"
exit 0

View File

@@ -1,30 +0,0 @@
FROM quay.io/centos/centos:stream8
ENV container=docker
RUN rm -fv /var/cache/dnf/metadata_lock.pid; \
dnf makecache; \
dnf --assumeyes install \
/usr/bin/python3 \
/usr/bin/python3-config \
/usr/bin/dnf-3 \
sudo \
bash \
systemd \
procps-ng \
iproute && \
dnf clean all; \
(cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*; \
rm -rf /var/cache/dnf/;
STOPSIGNAL RTMIN+3
VOLUME ["/sys/fs/cgroup"]
CMD ["/usr/sbin/init"]

View File

@@ -1,19 +0,0 @@
---
driver:
name: docker
platforms:
- name: c8s-build
image: "quay.io/centos/centos:stream8"
dockerfile: Dockerfile
hostname: ipaserver.test.local
dns_servers:
- 8.8.8.8
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare-build.yml
prerun: false

View File

@@ -1,19 +0,0 @@
---
driver:
name: docker
platforms:
- name: c8s
image: quay.io/ansible-freeipa/upstream-tests:c8s
pre_build_image: true
hostname: ipaserver.test.local
dns_servers:
- 127.0.0.1
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare.yml
prerun: false

View File

@@ -1,29 +0,0 @@
FROM quay.io/centos/centos:stream9
ENV container=docker
RUN rm -fv /var/cache/dnf/metadata_lock.pid; \
dnf makecache; \
dnf --assumeyes install \
/usr/bin/python3 \
/usr/bin/dnf-3 \
sudo \
bash \
systemd \
procps-ng \
iproute && \
dnf clean all; \
(cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*; \
rm -rf /var/cache/dnf/;
STOPSIGNAL RTMIN+3
VOLUME ["/sys/fs/cgroup"]
CMD ["/usr/sbin/init"]

View File

@@ -1,19 +0,0 @@
---
driver:
name: docker
platforms:
- name: c9s-build
image: "quay.io/centos/centos:stream9"
dockerfile: Dockerfile
hostname: ipaserver.test.local
dns_servers:
- 8.8.8.8
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare-build.yml
prerun: false

View File

@@ -1,19 +0,0 @@
---
driver:
name: docker
platforms:
- name: c9s
image: quay.io/ansible-freeipa/upstream-tests:c9s
pre_build_image: true
hostname: ipaserver.test.local
dns_servers:
- 127.0.0.1
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare.yml
prerun: false

View File

@@ -1,19 +0,0 @@
---
driver:
name: docker
platforms:
- name: centos-7-build
image: centos/systemd
pre_build_image: true
hostname: ipaserver.test.local
dns_servers:
- 8.8.8.8
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare-build.yml
prerun: false

View File

@@ -1,19 +0,0 @@
---
driver:
name: docker
platforms:
- name: centos-7
image: quay.io/ansible-freeipa/upstream-tests:centos-7
pre_build_image: true
hostname: ipaserver.test.local
dns_servers:
- 127.0.0.1
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare.yml
prerun: false

View File

@@ -1 +0,0 @@
fedora-latest

View File

@@ -1,30 +0,0 @@
FROM fedora:latest
ENV container=docker
RUN rm -fv /var/cache/dnf/metadata_lock.pid; \
dnf makecache; \
dnf --assumeyes install \
/usr/bin/python3 \
/usr/bin/python3-config \
/usr/bin/dnf-3 \
sudo \
bash \
systemd \
procps-ng \
iproute && \
dnf clean all; \
(cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*; \
rm -rf /var/cache/dnf/;
STOPSIGNAL RTMIN+3
VOLUME ["/sys/fs/cgroup"]
CMD ["/usr/sbin/init"]

View File

@@ -1,19 +0,0 @@
---
driver:
name: docker
platforms:
- name: fedora-latest-build
image: "fedora:latest"
dockerfile: Dockerfile
hostname: ipaserver.test.local
dns_servers:
- 8.8.8.8
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare-build.yml
prerun: false

View File

@@ -1,19 +0,0 @@
---
driver:
name: docker
platforms:
- name: fedora-latest
image: quay.io/ansible-freeipa/upstream-tests:fedora-latest
pre_build_image: true
hostname: ipaserver.test.local
dns_servers:
- 127.0.0.1
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare.yml
prerun: false

View File

@@ -1,30 +0,0 @@
FROM fedora:rawhide
ENV container=docker
RUN rm -fv /var/cache/dnf/metadata_lock.pid; \
dnf makecache; \
dnf --assumeyes install \
/usr/bin/python3 \
/usr/bin/python3-config \
/usr/bin/dnf-3 \
sudo \
bash \
systemd \
procps-ng \
iproute && \
dnf clean all; \
(cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*; \
rm -rf /var/cache/dnf/;
STOPSIGNAL RTMIN+3
VOLUME ["/sys/fs/cgroup"]
CMD ["/usr/sbin/init"]

View File

@@ -1,19 +0,0 @@
---
driver:
name: docker
platforms:
- name: fedora-rawhide-build
image: "fedora:rawhide"
dockerfile: Dockerfile
hostname: ipaserver.test.local
dns_servers:
- 8.8.8.8
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare-build.yml
prerun: false

View File

@@ -1,19 +0,0 @@
---
driver:
name: docker
platforms:
- name: fedora-rawhide
image: quay.io/ansible-freeipa/upstream-tests:fedora-rawhide
pre_build_image: true
hostname: ipaserver.test.local
dns_servers:
- 127.0.0.1
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare.yml
prerun: false

View File

@@ -1 +0,0 @@
../../../plugins/modules/

View File

@@ -1 +0,0 @@
../../../plugins/module_utils/

View File

@@ -1,28 +0,0 @@
---
- name: Converge
hosts: all
tasks:
- include_tasks: prepare-common.yml
- name: Ensure sudo package is installed
package:
name: sudo
- name: Ensure nss package is updated
package:
name: nss
state: latest # noqa 403
- include_role:
name: ipaserver
vars:
ipaserver_setup_dns: yes
ipaserver_setup_kra: yes
ipaserver_auto_forwarders: yes
ipaserver_no_dnssec_validation: yes
ipaserver_auto_reverse: yes
ipaadmin_password: SomeADMINpassword
ipadm_password: SomeDMpassword
ipaserver_domain: test.local
ipaserver_realm: TEST.LOCAL
ipaclient_no_ntp: yes

View File

@@ -1,33 +0,0 @@
---
# IPA depends on IPv6 and without it dirsrv service won't start.
- name: Ensure IPv6 is ENABLED
ansible.posix.sysctl:
name: "{{ item.name }}"
value: "{{ item.value }}"
sysctl_set: yes
state: present
reload: yes
with_items:
- name: net.ipv6.conf.all.disable_ipv6
value: 0
- name: net.ipv6.conf.lo.disable_ipv6
value: 0
- name: net.ipv6.conf.eth0.disable_ipv6
value: 1
# Set fs.protected_regular to 0
# This is needed in some IPA versions in order to get KRA enabled.
# See https://pagure.io/freeipa/issue/7906 for more information.
- name: stat protected_regular
ansible.builtin.stat:
path: /proc/sys/fs/protected_regular
register: result
- name: Ensure fs.protected_regular is disabled
ansible.posix.sysctl:
name: fs.protected_regular
value: 0
sysctl_set: yes
state: present
reload: yes
when: result.stat.exists

View File

@@ -1,48 +0,0 @@
---
- name: Converge
hosts: all
tasks:
- include_tasks: prepare-common.yml
# In some distros DS won't start up after reboot
# This is due to a problem in 389-ds. See tickets:
# * https://pagure.io/389-ds-base/issue/47429
# * https://pagure.io/389-ds-base/issue/51039
#
# To avoid this problem we create the directories before starting IPA.
- name: Ensure lock dirs for DS exists
ansible.builtin.file:
state: directory
owner: dirsrv
group: dirsrv
path: "{{ item }}"
mode: 0770
loop:
- /var/lock/dirsrv/
- /var/lock/dirsrv/slapd-TEST-LOCAL/
- name: Ensure IPA server is up an running
ansible.builtin.service:
name: ipa
state: started
- name: Wait for krb5dkc to be running
ansible.builtin.service_facts:
no_log: True
register: result
until: "'krb5kdc.service' in result.ansible_facts.services and \
result.ansible_facts.services['krb5kdc.service'].state == 'running'"
retries: 30
delay: 5
- name: Check if TGT is available for admin.
ansible.builtin.shell:
cmd: echo SomeADMINpassword | kinit -c ansible_freeipa_cache admin
register: result
until: not result.failed
retries: 30
delay: 5
- name: Cleanup TGT.
ansible.builtin.shell:
cmd: kdestroy -c ansible_freeipa_cache -A

View File

@@ -1 +0,0 @@
../../../roles/

View File

@@ -353,7 +353,15 @@ def api_check_ipa_version(oper, requested_version):
tasks.parse_ipa_version(requested_version))
def date_format(value):
def date_string(value):
# Convert datetime to gernalized time format string
if not isinstance(value, datetime):
raise ValueError("Invalid datetime type '%s'" % repr(value))
return value.strftime(LDAP_GENERALIZED_TIME_FORMAT)
def convert_date(value):
accepted_date_formats = [
LDAP_GENERALIZED_TIME_FORMAT, # generalized time
'%Y-%m-%dT%H:%M:%SZ', # ISO 8601, second precision
@@ -365,7 +373,7 @@ def date_format(value):
for _date_format in accepted_date_formats:
try:
return datetime.strptime(value, _date_format)
return date_string(datetime.strptime(value, _date_format))
except ValueError:
pass
raise ValueError("Invalid date '%s'" % value)
@@ -518,6 +526,10 @@ def module_params_get(module, name, allow_empty_list_item=False):
def module_params_get_lowercase(module, name, allow_empty_list_item=False):
value = module_params_get(module, name, allow_empty_list_item)
return convert_param_value_to_lowercase(value)
def convert_param_value_to_lowercase(value):
if isinstance(value, list):
value = [v.lower() for v in value]
if isinstance(value, (str, unicode)):
@@ -1576,3 +1588,232 @@ class IPAAnsibleModule(AnsibleModule):
ts = time.time()
# pylint: disable=super-with-arguments
super(IPAAnsibleModule, self).warn("%f %s" % (ts, warning))
class EntryFactory:
"""
Implement an Entry Factory to extract objects from modules.
When defining an ansible-freeipa module which allows the setting of
multiple objects in a single task, the object parameters can be set
as a set of parameters, or as a list of dictionaries with multiple
objects.
The EntryFactory abstracts the extraction of the entry values so
that the entries set in a module can be treated as a list of objects
independent of the way the objects have been defined (as single object
defined by its parameters or as a list).
Parameters
----------
ansible_module: The ansible module to be processed.
invalid_params: The list of invalid parameters for the current
state/action combination.
multiname: The name of the list of objects parameters.
params: a dict of the entry parameters with its configuration as a
dict. The 'convert' configuration is a list of functions to be
applied, in order, to the provided value for the paarameter. Any
other configuration field is ignored in the current implementation.
validate_entry: an optional function to validate the entry values.
This function is called after the parameters for the current
state/action are checked, and can be used to perform further
validation or modification to the entry values. If the entry is
not valid, 'fail_json' should be called. The function must return
the entry, modified or not. The funcion signature is
'def fn(module:IPAAnsibleModule, entry: Entry) -> Entry:'
**user_vars: any other keyword argument is passed to the
validate_entry callback as user data.
Example
-------
def validate_entry(module, entry, mydata):
if (something_is_wrong(entry)):
module.fail_json(msg=f"Something wrong with {entry.name}")
entry.some_field = mydata
return entry
def main():
# ...
# Create param mapping, all moudle parameters must be
# present as keys of this dictionary
params = {
"name": {},
"description": {}
"user": {
"convert": [convert_param_value_to_lowercase]
},
"group": {"convert": [convert_param_value_to_lowercase]}
}
entries = EntryFactory(
module, invalid_params, "entries", params,
validate_entry=validate_entry,
mydata=1234
)
#...
with module.ipa_connect(context=context):
# ...
for entry in entries:
# process entry and create commands
# ...
"""
def __init__(
self,
ansible_module,
invalid_params,
multiname,
params,
validate_entry=None,
**user_vars
):
"""Initialize the Entry Factory."""
self.ansible_module = ansible_module
self.invalid_params = set(invalid_params)
self.multiname = multiname
self.params = params
self.convert = {
param: (config or {}).get("convert", [])
for param, config in params.items()
}
self.validate_entry = validate_entry
self.user_vars = user_vars
self.__entries = self._get_entries()
def __iter__(self):
"""Initialize factory iterator."""
return iter(self.__entries)
def __next__(self):
"""Retrieve next entry."""
return next(self.__entries)
def check_invalid_parameter_usage(self, entry_dict, fail_on_check=True):
"""
Check if entry_dict parameters are valid for the current state/action.
Parameters
----------
entry_dict: A dictionary representing the module parameters.
fail_on_check: If set to True wil make the module execution fail
if invalid parameters are used.
Return
------
If fail_on_check is not True, returns True if the entry parameters
are valid and execution should proceed, False otherwise.
"""
state = self.ansible_module.params_get("state")
action = self.ansible_module.params_get("action")
if action is None:
msg = "Arguments '{0}' can not be used with state '{1}'"
else:
msg = "Arguments '{0}' can not be used with action " \
"'{2}' and state '{1}'"
entry_params = set(k for k, v in entry_dict.items() if v is not None)
match_invalid = self.invalid_params & entry_params
if match_invalid:
if fail_on_check:
self.ansible_module.fail_json(
msg=msg.format(", ".join(match_invalid), state, action))
return False
if not entry_dict.get("name"):
if fail_on_check:
self.ansible_module.fail_json(msg="Entry 'name' is not set.")
return False
return True
class Entry:
"""Provide an abstraction to handle module entries."""
def __init__(self, values):
"""Initialize entry to be used as dict or object."""
self.values = values
for key, value in values.items():
setattr(self, key, value)
def copy(self):
"""Make a copy of the entry."""
return EntryFactory.Entry(self.values.copy())
def __setitem__(self, item, value):
"""Allow entries to be treated as dictionaries."""
self.values[item] = value
setattr(self, item, value)
def __getitem__(self, item):
"""Allow entries to be treated as dictionaries."""
return self.values[item]
def __setattr__(self, attrname, value):
if attrname != "values" and attrname in self.values:
self.values[attrname] = value
super().__setattr__(attrname, value)
def __repr__(self):
"""Provide a string representation of the stored values."""
return repr(self.values)
def _get_entries(self):
"""Retrieve all entries from the module."""
def copy_entry_and_set_name(entry, name):
_result = entry.copy()
_result.name = name
return _result
names = self.ansible_module.params_get("name")
if names is not None:
if not isinstance(names, list):
names = [names]
# Get entrie(s) defined by the 'name' parameter.
# For most states and modules, 'name' will represent a single
# entry, but for some states, like 'absent', it could be a
# list of names.
_entry = self._extract_entry(
self.ansible_module,
IPAAnsibleModule.params_get
)
# copy attribute values if 'name' returns a list
_entries = [
copy_entry_and_set_name(_entry, _name)
for _name in names
]
else:
_entries = [
self._extract_entry(data, dict.get)
for data in self.ansible_module.params_get(self.multiname)
]
return _entries
def _extract_entry(self, data, param_get):
"""Extract an entry from the given data, using the given method."""
def get_entry_param_value(parameter, conversions):
_value = param_get(data, parameter)
if _value and conversions:
for fn in conversions:
_value = fn(_value)
return _value
# Build 'parameter: value' mapping for all module parameters
_entry = {
parameter: get_entry_param_value(parameter, conversions)
for parameter, conversions in self.convert.items()
}
# Check if any invalid parameter is used.
self.check_invalid_parameter_usage(_entry)
# Create Entry object
_result = EntryFactory.Entry(_entry)
# Call entry validation callback, if provided.
if self.validate_entry:
_result = self.validate_entry(
self.ansible_module, _result, **self.user_vars)
return _result

File diff suppressed because it is too large Load Diff

View File

@@ -739,10 +739,10 @@ user:
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, date_format, \
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, convert_date, \
encode_certificate, load_cert_from_str, DN_x500_text, to_text, \
ipalib_errors, gen_add_list, gen_intersection_list, \
convert_input_certificates
convert_input_certificates, date_string
from ansible.module_utils import six
if six.PY3:
unicode = str
@@ -758,6 +758,10 @@ def find_user(module, name):
except ipalib_errors.NotFound:
return None
# Convert datetime to proper string representation
for _expkey in ["krbpasswordexpiration", "krbprincipalexpiration"]:
if _expkey in _result:
_result[_expkey] = [date_string(x) for x in _result[_expkey]]
# Transform each principal to a string
_result["krbprincipalname"] = [
to_text(x) for x in (_result.get("krbprincipalname") or [])
@@ -1172,12 +1176,12 @@ def main():
if principalexpiration is not None:
if principalexpiration[:-1] != "Z":
principalexpiration = principalexpiration + "Z"
principalexpiration = date_format(principalexpiration)
principalexpiration = convert_date(principalexpiration)
passwordexpiration = ansible_module.params_get("passwordexpiration")
if passwordexpiration is not None:
if passwordexpiration[:-1] != "Z":
passwordexpiration = passwordexpiration + "Z"
passwordexpiration = date_format(passwordexpiration)
passwordexpiration = convert_date(passwordexpiration)
password = ansible_module.params_get("password")
random = ansible_module.params_get("random")
uid = ansible_module.params_get("uid")
@@ -1310,12 +1314,12 @@ def main():
if principalexpiration is not None:
if principalexpiration[:-1] != "Z":
principalexpiration = principalexpiration + "Z"
principalexpiration = date_format(principalexpiration)
principalexpiration = convert_date(principalexpiration)
passwordexpiration = user.get("passwordexpiration")
if passwordexpiration is not None:
if passwordexpiration[:-1] != "Z":
passwordexpiration = passwordexpiration + "Z"
passwordexpiration = date_format(passwordexpiration)
passwordexpiration = convert_date(passwordexpiration)
password = user.get("password")
random = user.get("random")
uid = user.get("uid")

View File

@@ -5,6 +5,5 @@ flake8==7.0.0
flake8-bugbear
pylint>=3.2
wrapt==1.14.1
pydocstyle==6.3.0
yamllint==1.35.1
ansible-lint>=24.5.0

View File

@@ -28,10 +28,6 @@ per-file-ignores =
plugins/*:E402
roles/*:E402
[pydocstyle]
inherit = false
ignore = D1,D212,D203
[pylint.MASTER]
disable =
consider-using-f-string, # f-string is not supported on Python2
@@ -56,7 +52,8 @@ disable =
too-many-branches,
too-many-locals,
fixme,
use-dict-literal
use-dict-literal,
too-many-positional-arguments
[pylint.BASIC]
good-names =
@@ -85,6 +82,9 @@ ignored-modules =
os,
SSSDConfig
[pylint.DESIGN]
max-attributes=12
[pylint.REFACTORING]
max-nested-blocks = 9

View File

@@ -36,6 +36,12 @@ environment variable. For example:
IPA_SSH_PASSWORD=<ipaserver_ssh_password> IPA_SERVER_HOST=<ipaserver_host_or_ip> pytest
```
If you want, or need to to set the Python interpreter to use, you must set `IPA_PYTHON_PATH`
environment variable. For example:
```
IPA_PYTHON_PATH=/usr/bin/python3.14 IPA_SERVER_HOST=<ipaserver_host_or_ip> pytest
```
To run a single test use the full path with the following format:
@@ -96,48 +102,16 @@ The pytests are tests that will execute small playbooks and then will verify the
To select only these tests on a test execution use the option `-m "not playbook"`.
## Running tests in a docker container
## Running tests in a container
It's also possible to run the tests in a container.
### Creating a container to run the tests
Before setting up a container you will need to install molecule framework:
```
pip install molecule-plugins[docker]
```
Now you can start a test container using the following command:
```
molecule create -s c8s
```
Note: Currently the containers available for running the tests are:
* fedora-latest
* centos-7
* c8s
* c9s
### Running the tests inside the container
It's also possible to run the tests in a container. Use the script `infra/image/start.sh` to start a container.
To run the tests you will use pytest (works the same as for VMs).
```
RUN_TESTS_IN_DOCKER=1 IPA_SERVER_HOST=c8s pytest
RUN_TESTS_IN_DOCKER=podman IPA_SERVER_HOST=ansbile-freeipa-tests pytest -m "playbook"
```
### Cleaning up after tests
After running the tests you should probably destroy the test container using:
```
molecule destroy -s c8s
```
See [Running the tests](#running-the-tests) section for more information on available options.
## Running local tests with upstream CI images
To run tests locally using the same images used by upstream CI use `utils/run-tests.sh`.
@@ -166,8 +140,6 @@ By default the tests are executed against the latest version of the Fedora image
utils/run-tests.sh -i c9s tests/host/test_host.yml
```
## Upcoming/desired improvements:
* A script to pre-config the complete test environment using virsh.
* A test matrix to run tests against different distros in parallel (probably using tox).
* A test matrix to run tests against different distros in parallel.

View File

@@ -1,85 +0,0 @@
---
trigger:
- master
pool:
vmImage: 'ubuntu-20.04'
stages:
# Fedora
- stage: Fedora_Ansible_Latest
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core"
# Fedora
- stage: Fedora_Ansible_min_supported
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core <2.14"
# Fedora
- stage: Fedora_Latest
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core >=2.14,<2.15"
# Galaxy on Fedora
- stage: Galaxy_Fedora_Latest
dependsOn: []
jobs:
- template: templates/galaxy_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core >=2.14,<2.15"
# CentOS 9 Stream
- stage: CentOS_9_Stream
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c9s
ansible_version: "-core >=2.14,<2.15"
# CentOS 8 Stream
- stage: CentOS_8_Stream
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c8s
ansible_version: "-core >=2.14,<2.15"
# CentOS 7
- stage: CentOS_7
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: centos-7
ansible_version: "-core >=2.14,<2.15"

View File

@@ -1,61 +0,0 @@
---
schedules:
- cron: "0 0 * * 0"
displayName: Weekly Sunday midnight build
branches:
include:
- master
always: true
trigger: none
pool:
vmImage: 'ubuntu-20.04'
stages:
- stage: CentOS_7
dependsOn: []
jobs:
- template: templates/build_container.yml
parameters:
job_name_suffix: Centos7
container_name: centos-7
build_scenario_name: centos-7-build
- stage: CentOS_8_Stream
dependsOn: []
jobs:
- template: templates/build_container.yml
parameters:
job_name_suffix: C8S
container_name: c8s
build_scenario_name: c8s-build
- stage: CentOS_9_Stream
dependsOn: []
jobs:
- template: templates/build_container.yml
parameters:
job_name_suffix: C9S
container_name: c9s
build_scenario_name: c9s-build
- stage: Fedora_Latest
dependsOn: []
jobs:
- template: templates/build_container.yml
parameters:
job_name_suffix: FedoraLatest
container_name: fedora-latest
build_scenario_name: fedora-latest-build
- stage: Fedora_Rawhide
dependsOn: []
jobs:
- template: templates/build_container.yml
parameters:
job_name_suffix: FedoraRawhide
container_name: fedora-rawhide
build_scenario_name: fedora-rawhide-build

View File

@@ -1,243 +0,0 @@
---
schedules:
- cron: "0 19 * * *"
displayName: Nightly Builds
branches:
include:
- master
always: true
trigger: none
pool:
vmImage: 'ubuntu-20.04'
stages:
# Fedora
- stage: FedoraLatest_Ansible_Core_2_13
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core >=2.13,<2.14"
- stage: FedoraLatest_Ansible_Core_2_14
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core >=2.14,<2.15"
- stage: FedoraLatest_Ansible_Core_2_15
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core >=2.15,<2.16"
- stage: FedoraLatest_Ansible_latest
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: ""
# Galaxy on Fedora
- stage: Galaxy_FedoraLatest_Ansible_Core_2_13
dependsOn: []
jobs:
- template: templates/galaxy_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core >=2.13,<2.14"
- stage: Galaxy_FedoraLatest_Ansible_Core_2_14
dependsOn: []
jobs:
- template: templates/galaxy_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core >=2.14,<2.15"
- stage: Galaxy_FedoraLatest_Ansible_Core_2_15
dependsOn: []
jobs:
- template: templates/galaxy_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core >=2.15,<2.16"
- stage: Galaxy_FedoraLatest_Ansible_latest
dependsOn: []
jobs:
- template: templates/galaxy_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: ""
# Fedora Rawhide
- stage: FedoraRawhide_Ansible_Core_2_13
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-rawhide
ansible_version: "-core >=2.13,<2.14"
- stage: FedoraRawhide_Ansible_Core_2_14
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-rawhide
ansible_version: "-core >=2.14,<2.15"
- stage: FedoraRawhide_Ansible_Core_2_15
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-rawhide
ansible_version: "-core >=2.15,<2.16"
- stage: FedoraRawhide_Ansible_latest
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-rawhide
ansible_version: ""
# CentoOS 9 Stream
- stage: c9s_Ansible_Core_2_13
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c9s
ansible_version: "-core >=2.13,<2.14"
- stage: c9s_Ansible_Core_2_14
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c9s
ansible_version: "-core >=2.14,<2.15"
- stage: c9s_Ansible_Core_2_15
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c9s
ansible_version: "-core >=2.15,<2.16"
- stage: c9s_Ansible_latest
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c9s
ansible_version: ""
# CentOS 8 Stream
- stage: c8s_Ansible_Core_2_13
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c8s
ansible_version: "-core >=2.13,<2.14"
- stage: c8s_Ansible_Core_2_14
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c8s
ansible_version: "-core >=2.14,<2.15"
- stage: c8s_Ansible_Core_2_15
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c8s
ansible_version: "-core >=2.15,<2.16"
- stage: c8s_Ansible_latest
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c8s
ansible_version: ""
# CentOS 7
- stage: CentOS7_Ansible_Core_2_13
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: centos-7
ansible_version: "-core >=2.13,<2.14"
- stage: CentOS7_Ansible_Core_2_14
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: centos-7
ansible_version: "-core >=2.14,<2.15"
- stage: CentOS7_Ansible_Core_2_15
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: centos-7
ansible_version: "-core >=2.15,<2.16"
- stage: CentOS7_Ansible_latest
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: centos-7
ansible_version: ""

View File

@@ -1,74 +0,0 @@
---
trigger:
- master
pool:
vmImage: 'ubuntu-20.04'
stages:
# Fedora
- stage: Fedora_Latest
dependsOn: []
jobs:
- template: templates/fast_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core >=2.14,<2.15"
# Galaxy on Fedora
- stage: Galaxy_Fedora_Latest
dependsOn: []
jobs:
- template: templates/fast_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core >=2.14,<2.15"
# CentOS 9 Stream
- stage: CentOS_9_Stream
dependsOn: []
jobs:
- template: templates/fast_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c9s
ansible_version: "-core >=2.14,<2.15"
# CentOS 8 Stream
- stage: CentOS_8_Stream
dependsOn: []
jobs:
- template: templates/fast_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c8s
ansible_version: "-core >=2.14,<2.15"
# CentOS 7
- stage: CentOS_7
dependsOn: []
jobs:
- template: templates/fast_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: centos-7
ansible_version: "-core >=2.14,<2.15"
# Rawhide
- stage: Fedora_Rawhide
dependsOn: []
jobs:
- template: templates/fast_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-rawhide
ansible_version: "-core >=2.14,<2.15"

View File

@@ -1,43 +0,0 @@
---
parameters:
- name: job_name_suffix
type: string
- name: container_name
type: string
- name: build_scenario_name
type: string
- name: python_version
type: string
default: 3.x
jobs:
- job: BuildTestImage${{ parameters.job_name_suffix }}
displayName: Build ${{ parameters.container_name }} test container
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '${{ parameters.python_version }}'
- script: python -m pip install --upgrade pip setuptools wheel ansible
retryCountOnTaskFailure: 5
displayName: Install tools
- script: pip install molecule-plugins[docker] "requests<2.29"
retryCountOnTaskFailure: 5
displayName: Install molecule
- script: molecule create -s ${{ parameters.build_scenario_name }}
retryCountOnTaskFailure: 5
displayName: Create test container
env:
ANSIBLE_LIBRARY: ./molecule
- script: |
docker stop ${{ parameters.build_scenario_name }}
docker commit ${{ parameters.build_scenario_name }} quay.io/ansible-freeipa/upstream-tests:${{ parameters.container_name }}
docker login -u="$QUAY_ROBOT_USERNAME" -p="$QUAY_ROBOT_TOKEN" quay.io
docker push quay.io/ansible-freeipa/upstream-tests:${{ parameters.container_name }}
displayName: Save image and upload
env:
# Secrets needs to be mapped as env vars to work properly
QUAY_ROBOT_TOKEN: $(QUAY_ROBOT_TOKEN)

View File

@@ -1,27 +0,0 @@
---
parameters:
- name: scenario
type: string
default: fedora-latest
- name: build_number
type: string
- name: ansible_version
type: string
default: ""
jobs:
- template: playbook_fast.yml
parameters:
group_number: 1
number_of_groups: 1
build_number: ${{ parameters.build_number }}
scenario: ${{ parameters.scenario }}
ansible_version: ${{ parameters.ansible_version }}
python_version: '< 3.12'
# - template: pytest_tests.yml
# parameters:
# build_number: ${{ parameters.build_number }}
# scenario: ${{ parameters.scenario }}
# ansible_version: ${{ parameters.ansible_version }}
# python_version: '< 3.12'

View File

@@ -1,65 +0,0 @@
---
parameters:
- name: build_number
type: string
- name: scenario
type: string
default: fedora-latest
- name: ansible_version
type: string
default: ""
- name: python_version
type: string
default: 3.x
jobs:
- job: Test_PyTests
displayName: Run pytests on ${{ parameters.scenario }}
timeoutInMinutes: 240
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '${{ parameters.python_version }}'
- script: |
pip install \
"molecule-plugins[docker]" \
"requests<2.29" \
"ansible${{ parameters.ansible_version }}"
retryCountOnTaskFailure: 5
displayName: Install molecule and Ansible
- script: ansible-galaxy collection install community.docker ansible.posix
retryCountOnTaskFailure: 5
displayName: Install Ansible collections
- script: pip install -r requirements-tests.txt
retryCountOnTaskFailure: 5
displayName: Install dependencies
- script: |
utils/build-galaxy-release.sh -i
molecule create -s ${{ parameters.scenario }}
retryCountOnTaskFailure: 5
displayName: Setup test container
env:
ANSIBLE_LIBRARY: ./molecule
- script: |
cd ~/.ansible/collections/ansible_collections/freeipa/ansible_freeipa
pytest \
-m "not playbook" \
--verbose \
--color=yes \
--junit-xml=TEST-results-pytests.xml
displayName: Run tests
env:
IPA_SERVER_HOST: ${{ parameters.scenario }}
RUN_TESTS_IN_DOCKER: true
IPA_VERBOSITY: "-vvv"
- task: PublishTestResults@2
inputs:
mergeTestResults: true
testRunTitle: PlaybookTests-Build${{ parameters.build_number }}
condition: succeededOrFailed()

View File

@@ -1,86 +0,0 @@
---
parameters:
- name: group_number
type: number
default: 1
- name: number_of_groups
type: number
default: 1
- name: scenario
type: string
default: fedora-latest
- name: ansible_version
type: string
default: ""
- name: python_version
type: string
default: 3.x
- name: build_number
type: string
jobs:
- job: Test_Group${{ parameters.group_number }}
displayName: Run playbook tests ${{ parameters.scenario }} (${{ parameters.group_number }}/${{ parameters.number_of_groups }})
timeoutInMinutes: 240
variables:
- template: variables.yaml
- template: variables_${{ parameters.scenario }}.yaml
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '${{ parameters.python_version }}'
- script: |
pip install \
"molecule-plugins[docker]" \
"requests<2.29" \
"ansible${{ parameters.ansible_version }}"
retryCountOnTaskFailure: 5
displayName: Install molecule and Ansible
- script: ansible-galaxy collection install community.docker ansible.posix
retryCountOnTaskFailure: 5
displayName: Install Ansible collections
- script: pip install -r requirements-tests.txt
retryCountOnTaskFailure: 5
displayName: Install dependencies
- script: |
utils/build-galaxy-release.sh -i
molecule create -s ${{ parameters.scenario }}
retryCountOnTaskFailure: 5
displayName: Setup test container
env:
ANSIBLE_LIBRARY: ./molecule
- script: |
python utils/check_test_configuration.py ${{ parameters.scenario }}
displayName: Check scenario test configuration
- script: |
cd ~/.ansible/collections/ansible_collections/freeipa/ansible_freeipa
pytest \
-m "playbook" \
--verbose \
--color=yes \
--splits=${{ parameters.number_of_groups }} \
--group=${{ parameters.group_number }} \
--randomly-seed=$(date "+%Y%m%d") \
--junit-xml=TEST-results-group-${{ parameters.group_number }}.xml
displayName: Run playbook tests
env:
IPA_SERVER_HOST: ${{ parameters.scenario }}
RUN_TESTS_IN_DOCKER: true
IPA_DISABLED_MODULES: ${{ variables.ipa_disabled_modules }}
IPA_DISABLED_TESTS: ${{ variables.ipa_disabled_tests }}
IPA_ENABLED_MODULES: ${{ variables.ipa_enabled_modules }}
IPA_ENABLED_TESTS: ${{ variables.ipa_enabled_tests }}
IPA_VERBOSITY: "-vvv"
- task: PublishTestResults@2
inputs:
mergeTestResults: true
testRunTitle: PlaybookTests-Build${{ parameters.build_number }}
condition: succeededOrFailed()

View File

@@ -1,46 +0,0 @@
---
parameters:
- name: scenario
type: string
default: fedora-latest
- name: build_number
type: string
- name: ansible_version
type: string
default: ""
jobs:
- template: galaxy_script.yml
parameters:
group_number: 1
number_of_groups: 3
build_number: ${{ parameters.build_number }}
scenario: ${{ parameters.scenario }}
ansible_version: ${{ parameters.ansible_version }}
python_version: '< 3.12'
- template: galaxy_script.yml
parameters:
group_number: 2
number_of_groups: 3
build_number: ${{ parameters.build_number }}
scenario: ${{ parameters.scenario }}
ansible_version: ${{ parameters.ansible_version }}
python_version: '< 3.12'
- template: galaxy_script.yml
parameters:
group_number: 3
number_of_groups: 3
build_number: ${{ parameters.build_number }}
scenario: ${{ parameters.scenario }}
ansible_version: ${{ parameters.ansible_version }}
python_version: '< 3.12'
# Temporarily disable due to issues with ansible docker plugin.
#- template: galaxy_pytest_script.yml
# parameters:
# build_number: ${{ parameters.build_number }}
# scenario: ${{ parameters.scenario }}
# ansible_version: ${{ parameters.ansible_version }}
# python_version: '< 3.12'

View File

@@ -1,46 +0,0 @@
---
parameters:
- name: scenario
type: string
default: fedora-latest
- name: build_number
type: string
- name: ansible_version
type: string
default: ""
jobs:
- template: playbook_tests.yml
parameters:
group_number: 1
number_of_groups: 3
build_number: ${{ parameters.build_number }}
scenario: ${{ parameters.scenario }}
ansible_version: ${{ parameters.ansible_version }}
python_version: '< 3.12'
- template: playbook_tests.yml
parameters:
group_number: 2
number_of_groups: 3
build_number: ${{ parameters.build_number }}
scenario: ${{ parameters.scenario }}
ansible_version: ${{ parameters.ansible_version }}
python_version: '< 3.12'
- template: playbook_tests.yml
parameters:
group_number: 3
number_of_groups: 3
build_number: ${{ parameters.build_number }}
scenario: ${{ parameters.scenario }}
ansible_version: ${{ parameters.ansible_version }}
python_version: '< 3.12'
# Temporarily disabled due to ansible docker plugin issue.
#- template: pytest_tests.yml
# parameters:
# build_number: ${{ parameters.build_number }}
# scenario: ${{ parameters.scenario }}
# ansible_version: ${{ parameters.ansible_version }}
# python_version: '< 3.12'

View File

@@ -1,92 +0,0 @@
---
parameters:
- name: group_number
type: number
default: 1
- name: number_of_groups
type: number
default: 1
- name: scenario
type: string
default: fedora-latest
- name: ansible_version
type: string
default: ""
- name: python_version
type: string
default: 3.x
- name: build_number
type: string
jobs:
- job: Test_Group${{ parameters.group_number }}
displayName: Run playbook tests ${{ parameters.scenario }} (${{ parameters.group_number }}/${{ parameters.number_of_groups }})
timeoutInMinutes: 360
variables:
- template: variables.yaml
- template: variables_${{ parameters.scenario }}.yaml
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '${{ parameters.python_version }}'
- script: |
pip install \
"molecule-plugins[docker]" \
"requests<2.29" \
"ansible${{ parameters.ansible_version }}"
retryCountOnTaskFailure: 5
displayName: Install molecule and Ansible
- script: ansible-galaxy collection install community.docker ansible.posix
retryCountOnTaskFailure: 5
displayName: Install Ansible collections
- script: pip install -r requirements-tests.txt
retryCountOnTaskFailure: 5
displayName: Install dependencies
- script: |
rm -rf ~/ansible
mkdir -p ~/.ansible/roles ~/.ansible/library ~/.ansible/module_utils
cp -a roles/* ~/.ansible/roles
cp -a plugins/modules/* ~/.ansible/library
cp -a plugins/module_utils/* ~/.ansible/module_utils
molecule create -s ${{ parameters.scenario }}
retryCountOnTaskFailure: 5
displayName: Setup test container
env:
ANSIBLE_LIBRARY: ./molecule
- script: |
. utils/set_test_modules
python utils/check_test_configuration.py ${{ parameters.scenario }}
displayName: Check scenario test configuration
- script: |
. utils/set_test_modules
if ! pytest \
-m "playbook" \
--verbose \
--color=yes \
--suppress-no-test-exit-code \
--splits=${{ parameters.number_of_groups }} \
--group=${{ parameters.group_number }} \
--randomly-seed=$(date "+%Y%m%d") \
--junit-xml=TEST-results-group-${{ parameters.group_number }}.xml
then
[ $? -eq 5 ] && true || false
fi
displayName: Run playbook tests
env:
IPA_SERVER_HOST: ${{ parameters.scenario }}
RUN_TESTS_IN_DOCKER: true
IPA_DISABLED_MODULES: ${{ variables.ipa_disabled_modules }}
IPA_DISABLED_TESTS: ${{ variables.ipa_disabled_tests }}
IPA_VERBOSITY: "-vvv"
- task: PublishTestResults@2
inputs:
mergeTestResults: true
testRunTitle: PlaybookTests-Build${{ parameters.build_number }}
condition: succeededOrFailed()

View File

@@ -1,88 +0,0 @@
---
parameters:
- name: group_number
type: number
default: 1
- name: number_of_groups
type: number
default: 1
- name: scenario
type: string
default: fedora-latest
- name: ansible_version
type: string
default: ""
- name: python_version
type: string
default: 3.x
- name: build_number
type: string
jobs:
- job: Test_Group${{ parameters.group_number }}
displayName: Run playbook tests ${{ parameters.scenario }} (${{ parameters.group_number }}/${{ parameters.number_of_groups }})
timeoutInMinutes: 240
variables:
- template: variables.yaml
- template: variables_${{ parameters.scenario }}.yaml
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '${{ parameters.python_version }}'
- script: |
pip install \
"molecule-plugins[docker]" \
"requests<2.29" \
"ansible${{ parameters.ansible_version }}"
retryCountOnTaskFailure: 5
displayName: Install molecule and Ansible
- script: ansible-galaxy collection install community.docker ansible.posix
retryCountOnTaskFailure: 5
displayName: Install Ansible collections
- script: pip install -r requirements-tests.txt
retryCountOnTaskFailure: 5
displayName: Install dependencies
- script: |
rm -rf ~/ansible
mkdir -p ~/.ansible/roles ~/.ansible/library ~/.ansible/module_utils
cp -a roles/* ~/.ansible/roles
cp -a plugins/modules/* ~/.ansible/library
cp -a plugins/module_utils/* ~/.ansible/module_utils
molecule create -s ${{ parameters.scenario }}
retryCountOnTaskFailure: 5
displayName: Setup test container
env:
ANSIBLE_LIBRARY: ./molecule
- script: |
python utils/check_test_configuration.py ${{ parameters.scenario }}
displayName: Check scenario test configuration
- script: |
pytest \
-m "playbook" \
--verbose \
--color=yes \
--splits=${{ parameters.number_of_groups }} \
--group=${{ parameters.group_number }} \
--randomly-seed=$(date "+%Y%m%d") \
--junit-xml=TEST-results-group-${{ parameters.group_number }}.xml
displayName: Run playbook tests
env:
IPA_SERVER_HOST: ${{ parameters.scenario }}
RUN_TESTS_IN_DOCKER: true
IPA_DISABLED_MODULES: ${{ variables.ipa_disabled_modules }}
IPA_DISABLED_TESTS: ${{ variables.ipa_disabled_tests }}
IPA_ENABLED_MODULES: ${{ variables.ipa_enabled_modules }}
IPA_ENABLED_TESTS: ${{ variables.ipa_enabled_tests }}
IPA_VERBOSITY: "-vvv"
- task: PublishTestResults@2
inputs:
mergeTestResults: true
testRunTitle: PlaybookTests-Build${{ parameters.build_number }}
condition: succeededOrFailed()

View File

@@ -1,75 +0,0 @@
---
parameters:
- name: build_number
type: string
- name: scenario
type: string
default: fedora-latest
- name: ansible_version
type: string
default: ""
- name: python_version
type: string
default: 3.x
jobs:
- job: Test_PyTests
displayName: Run pytests on ${{ parameters.scenario }}
timeoutInMinutes: 240
variables:
- template: variables.yaml
- template: variables_${{ parameters.scenario }}.yaml
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '${{ parameters.python_version }}'
- script: |
pip install \
"molecule-plugins[docker]" \
"requests<2.29" \
"ansible${{ parameters.ansible_version }}"
retryCountOnTaskFailure: 5
displayName: Install molecule and Ansible
- script: ansible-galaxy collection install community.docker ansible.posix
retryCountOnTaskFailure: 5
displayName: Install Ansible collections
- script: pip install -r requirements-tests.txt
retryCountOnTaskFailure: 5
displayName: Install dependencies
- script: |
rm -rf ~/.ansible
mkdir -p ~/.ansible/roles ~/.ansible/library ~/.ansible/module_utils
cp -a roles/* ~/.ansible/roles
cp -a plugins/modules/* ~/.ansible/library
cp -a plugins/module_utils/* ~/.ansible/module_utils
molecule create -s ${{ parameters.scenario }}
retryCountOnTaskFailure: 5
displayName: Setup test container
env:
ANSIBLE_LIBRARY: ./molecule
- script: |
pytest \
-m "not playbook" \
--verbose \
--color=yes \
--junit-xml=TEST-results-pytests.xml
displayName: Run tests
env:
IPA_SERVER_HOST: ${{ parameters.scenario }}
RUN_TESTS_IN_DOCKER: true
IPA_DISABLED_MODULES: ${{ variables.ipa_disabled_modules }}
IPA_DISABLED_TESTS: ${{ variables.ipa_disabled_tests }}
IPA_ENABLED_MODULES: ${{ variables.ipa_enabled_modules }}
IPA_ENABLED_TESTS: ${{ variables.ipa_enabled_tests }}
IPA_VERBOSITY: "-vvv"
- task: PublishTestResults@2
inputs:
mergeTestResults: true
testRunTitle: PlaybookTests-Build${{ parameters.build_number }}
condition: succeededOrFailed()

View File

@@ -40,7 +40,7 @@
- name: Create CSR
ansible.builtin.shell:
cmd: "openssl req -newkey rsa:1024 -keyout /dev/null -nodes -subj /CN=certhost.{{ ipa_domain }}"
cmd: "openssl req -newkey rsa:2048 -keyout /dev/null -nodes -subj /CN=certhost.{{ ipa_domain }}"
register: host_req
- name: Create CSR file

View File

@@ -51,7 +51,7 @@
- name: Create signing request for certificate
ansible.builtin.shell:
cmd: "openssl req -newkey rsa:1024 -keyout /dev/null -nodes -subj /CN=certservice.{{ ipa_domain }}"
cmd: "openssl req -newkey rsa:2048 -keyout /dev/null -nodes -subj /CN=certservice.{{ ipa_domain }}"
register: service_req
- name: Create CSR file

View File

@@ -36,7 +36,7 @@
- name: Crete CSR
ansible.builtin.shell:
cmd:
'openssl req -newkey rsa:1024 -keyout /dev/null -nodes -subj /CN=certuser -reqexts IECUserRoles
'openssl req -newkey rsa:2048 -keyout /dev/null -nodes -subj /CN=certuser -reqexts IECUserRoles
-config <(cat /etc/pki/tls/openssl.cnf; printf "[IECUserRoles]\n1.2.840.10070.8.1=ASN1:UTF8String:hello world")'
executable: /bin/bash
register: user_req

View File

@@ -1,15 +0,0 @@
---
- name: Test services absent
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Include generate_test_data.yml
ansible.builtin.include_tasks: generate_test_data.yml
- name: Services absent len:{{ service_list | length }}
ipaservice:
ipaadmin_password: SomeADMINpassword
services: "{{ service_absent_list }}"
state: absent

View File

@@ -8,6 +8,18 @@
- name: Include generate_test_data.yml
ansible.builtin.include_tasks: generate_test_data.yml
- name: Cleanup Services len:{{ service_list | length }}
ipaservice:
ipaadmin_password: SomeADMINpassword
services: "{{ service_absent_list }}"
state: absent
- name: Cleanup Hosts len:{{ host_list | length }}
ipahost:
ipaadmin_password: SomeADMINpassword
hosts: "{{ host_absent_list }}"
state: absent
- name: Hosts present len:{{ host_list | length }}
ipahost:
ipaadmin_password: SomeADMINpassword

View File

@@ -3,11 +3,15 @@
- name: Test sudorule
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: true
gather_facts: false
tasks:
# setup
- name: Ensure DNS Ansible facts are available
ansible.builtin.setup:
gather_subset: dns
- name: Ensure test user is present
ipauser:
ipaadmin_password: SomeADMINpassword
@@ -1157,7 +1161,7 @@
hostmask: 192.168.120.0/24
action: member
register: result
check_mode: yes
check_mode: true
failed_when: not result.changed or result.failed
- name: Ensure sudorule hostmask member is present

View File

@@ -1,13 +1,22 @@
---
- name: Test sudorule user category
hosts: ipaserver
become: yes
gather_facts: yes
become: false
gather_facts: false
tasks:
- name: Get Domain from the server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
- name: Test sudorule single hostnames
block:
# setup test environment
- name: Ensure ipaserver_domain is set
when: ipaserver_domain is not defined
block:
- name: Retrieve host information
ansible.builtin.setup:
gather_subset: dns
- name: Get Domain from the server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
- name: Ensure sudorules are absent
ipasudorule:

View File

@@ -1,8 +1,8 @@
---
- name: Test sudorule
hosts: ipaclients, ipaserver
become: no
gather_facts: no
become: false
gather_facts: false
tasks:
- name: Include FreeIPA facts.
@@ -37,3 +37,15 @@
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
- name: Test sudorule using client context, in client host.
ansible.builtin.import_playbook: test_sudorules.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test sudorule using client context, in server host.
ansible.builtin.import_playbook: test_sudorules.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client

View File

@@ -1,8 +1,8 @@
---
- name: Test sudorule members should be case insensitive.
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: no
gather_facts: no
become: false
gather_facts: false
vars:
groups_present:
@@ -37,7 +37,7 @@
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}.{{ ipa_domain }}"
force: yes
force: true
loop: "{{ groups_present }}"
- name: Ensure test users exist.

View File

@@ -1,17 +1,22 @@
---
- name: Test sudorule with single hostnames.
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: no
gather_facts: no
become: false
gather_facts: false
tasks:
- name: Test sudorule single hostnames
block:
# setup test environment
- name: Get Domain from the server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
- name: Ensure ipaserver_domain is set
when: ipaserver_domain is not defined
block:
- name: Retrieve host information
ansible.builtin.setup:
gather_subset: dns
- name: Get Domain from the server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
- name: Ensure test sudo rule is absent
ipasudorule:
@@ -24,9 +29,9 @@
ipaadmin_password: SomeADMINpassword
hosts:
- name: "host01.{{ ipaserver_domain }}"
force: yes
force: true
- name: "host02.{{ ipaserver_domain }}"
force: yes
force: true
# start tests
- name: Ensure sudorule exist with host member using FQDN.

View File

@@ -0,0 +1,382 @@
---
- name: Test sudorule
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: false
gather_facts: false
module_defaults:
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipasudocmd:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
tasks:
# setup
- name: Ensure ansible facts for DNS are available
ansible.builtin.setup:
gather_subset: dns
- name: Ensure test users are absent
ipauser:
name:
- user01
- user02
state: absent
- name: Ensure test groups are absent
ipagroup:
name:
- group01
- group02
state: absent
- name: Ensure test hostgroup is absent
ipahostgroup:
name: cluster
state: absent
- name: Ensure test users are present
ipauser:
users:
- name: user01
first: user
last: zeroone
- name: user02
first: user
last: zerotwo
- name: Ensure groups are present
ipagroup:
groups:
- name: group01
user: user01
- name: group02
- name: Ensure sudocmdgroup is absent
ipasudocmdgroup:
name: test_sudorule_cmdgroup
state: absent
- name: Ensure hostgroup is present, with a host.
ipahostgroup:
name: cluster
host: "{{ ansible_facts['fqdn'] }}"
- name: Ensure some sudocmds are available
ipasudocmd:
name:
- /sbin/ifconfig
- /usr/bin/vim
- /usr/bin/emacs
state: present
- name: Ensure sudocmdgroup is available
ipasudocmdgroup:
name: test_sudorule_cmdgroup
sudocmd: /usr/bin/vim
state: present
- name: Ensure another sudocmdgroup is available
ipasudocmdgroup:
name: test_sudorule_cmdgroup_2
sudocmd: /usr/bin/emacs
state: present
- name: Ensure sudorules are absent
ipasudorule:
name:
- testrule1
- testrule2
- allusers
- allhosts
- allcommands
state: absent
# tests
- name: Run sudorules tests.
block:
- name: Ensure sudorules are present
ipasudorule:
sudorules:
- name: testrule1
- name: testrule2
- name: allhosts
- name: allcommands
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorules are present, again
ipasudorule:
sudorules:
- name: testrule1
- name: testrule2
- name: allhosts
- name: allcommands
register: result
failed_when: result.changed or result.failed
- name: Ensure testrule1 and testrule2 are absent
ipasudorule:
sudorules:
- name: testrule1
- name: testrule2
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure testrule1 and testrule2 are absent, again
ipasudorule:
sudorules:
- name: testrule1
- name: testrule2
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure allhosts and allcommands sudorules are still present
ipasudorule:
sudorules:
- name: allhosts
- name: allcomands
state: absent
check_mode: true
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorules with parameters are present
ipasudorule:
sudorules:
- name: testrule1
runasuser:
- user01
- name: testrule2
runasuser_group:
- group01
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorules with parameters are present, again
ipasudorule:
sudorules:
- name: testrule1
runasuser:
- user01
- name: testrule2
runasuser_group:
- group01
state: present
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorules with parameters are modified
ipasudorule:
sudorules:
- name: testrule1
runasuser:
- user02
- name: testrule2
runasuser_group:
- group02
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorules with parameters are modified again
ipasudorule:
sudorules:
- name: testrule1
runasuser:
- user02
- name: testrule2
runasuser_group:
- group02
state: present
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorules members can be modified
ipasudorule:
sudorules:
- name: testrule1
runasuser:
- user01
- name: testrule2
runasuser_group:
- group01
action: member
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorules members can modified, again
ipasudorule:
sudorules:
- name: testrule1
runasuser:
- user01
- user02
- name: testrule2
runasuser_group:
- group01
- group02
action: member
state: present
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorules members are absent
ipasudorule:
sudorules:
- name: testrule1
runasuser:
- user01
- name: testrule2
runasuser_group:
- group02
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorules members are absent, again
ipasudorule:
sudorules:
- name: testrule1
runasuser:
- user01
- name: testrule2
runasuser_group:
- group02
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure testrule1 and testrule2 are present, with proper attributes
ipasudorule:
sudorules:
- name: testrule1
runasuser:
- user02
- name: testrule2
runasuser_group:
- group01
state: present
register: result
failed_when: result.changed or result.failed
- name: Ensure testrule1 and testrule2 are disabled
ipasudorule:
sudorules:
- name: testrule1
- name: testrule2
state: disabled
register: result
failed_when: not result.changed or result.failed
- name: Ensure testrule1 and testrule2 are disabled, again
ipasudorule:
sudorules:
- name: testrule1
- name: testrule2
state: disabled
register: result
failed_when: result.changed or result.failed
- name: Ensure testrule1 and testrule2 are enabled
ipasudorule:
sudorules:
- name: testrule1
- name: testrule2
state: enabled
register: result
failed_when: not result.changed or result.failed
- name: Ensure testrule1 and testrule2 are enabled, again
ipasudorule:
sudorules:
- name: testrule1
- name: testrule2
state: enabled
register: result
failed_when: result.changed or result.failed
- name: Ensure multiple sudorules cannot be enabled with invalid parameters
ipasudorule:
sudorules:
- name: testrule1
runasuser: user01
- name: testrule2
runasuser: user01
state: enabled
register: result
failed_when: not result.failed and "Argument 'runasuser' can not be used with action 'sudorule' and state 'enabled'" not in result.msg
- name: Ensure multiple sudorules cannot be disabled with invalid parameters
ipasudorule:
sudorules:
- name: testrule1
runasuser: user01
- name: testrule2
runasuser: user01
state: disabled
register: result
failed_when: not result.failed and "Argument 'runasuser' can not be used with action 'sudorule' and state 'disabled'" not in result.msg
# cleanup
always:
- name: Cleanup sudorules
ipasudorule:
name:
- testrule1
- testrule2
- allusers
- allhosts
- allcommands
state: absent
- name: Ensure sudocmdgroup is absent
ipasudocmdgroup:
name:
- test_sudorule_cmdgroup
- test_sudorule_cmdgroup_2
state: absent
- name: Ensure sudocmds are absent
ipasudocmd:
name:
- /sbin/ifconfig
- /usr/bin/vim
- /usr/bin/emacs
state: absent
- name: Ensure hostgroup is absent.
ipahostgroup:
name: cluster
state: absent
- name: Ensure groups are absent
ipagroup:
name: group01,group02
state: absent
- name: Ensure user is absent
ipauser:
name: user01,user02
state: absent

View File

@@ -0,0 +1,311 @@
---
- name: Test sudorules members should be case insensitive.
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: false
gather_facts: false
module_defaults:
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipasudocmd:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
vars:
groups_present:
- eleMENT1
- Element2
- eLeMenT3
- ElemENT4
tasks:
- name: Test sudorule member case insensitive
block:
# SETUP
- name: Ensure domain name
ansible.builtin.set_fact:
ipa_domain: ipa.test
when: ipa_domain is not defined
- name: Ensure test groups are absent.
ipagroup:
name: "{{ groups_present }}"
state: absent
- name: Ensure test hostgroups are absent.
ipahostgroup:
name: "{{ groups_present }}"
state: absent
- name: Ensure test users are absent.
ipauser:
name: "{{ groups_present }}"
state: absent
- name: Ensure test groups exist.
ipagroup:
name: "{{ item }}"
loop: "{{ groups_present }}"
- name: Ensure test hostgroups exist.
ipahostgroup:
name: "{{ item }}"
loop: "{{ groups_present }}"
- name: Ensure test hosts exist.
ipahost:
name: "{{ item }}.{{ ipa_domain }}"
force: yes
loop: "{{ groups_present }}"
- name: Ensure test users exist.
ipauser:
name: "user{{ item }}"
first: "{{ item }}"
last: "{{ item }}"
loop: "{{ groups_present }}"
- name: Ensure sudorule do not exist
ipasudorule:
sudorules:
- name: "{{ item }}"
state: absent
loop: "{{ groups_present }}"
# TESTS
- name: Ensure sudorule exist with runasusers members
ipasudorule:
sudorules:
- name: "{{ item }}"
cmdcategory: all
runasuser: "user{{ item }}"
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or not result.changed
- name: Ensure sudorule exist with lowercase runasusers members
ipasudorule:
sudorules:
- name: "{{ item }}"
cmdcategory: all
runasuser: "user{{ item | lower }}"
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure sudorule exist with uppercase runasusers members
ipasudorule:
sudorules:
- name: "{{ item }}"
cmdcategory: all
runasuser: "user{{ item | upper }}"
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure sudorule exist with runasgroup members
ipasudorule:
sudorules:
- name: "{{ item }}"
cmdcategory: all
runasgroup: "{{ item }}"
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or not result.changed
- name: Ensure sudorule exist with lowercase runasgroup members
ipasudorule:
sudorules:
- name: "{{ item }}"
cmdcategory: all
runasgroup: "{{ item | lower }}"
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure sudorule exist with uppercase runasgroup members
ipasudorule:
sudorules:
- name: "{{ item }}"
cmdcategory: all
runasgroup: "{{ item | upper }}"
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure sudorule do not exist
ipasudorule:
sudorules:
- name: "{{ item }}"
state: absent
loop: "{{ groups_present }}"
#####
- name: Ensure sudorule exist with members
ipasudorule:
sudorules:
- name: "{{ item }}"
cmdcategory: all
hostgroup: "{{ item }}"
host: "{{ item }}.{{ ipa_domain }}"
group: "{{ item }}"
user: "user{{ item }}"
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or not result.changed
- name: Ensure sudorule exist with members, lowercase
ipasudorule:
sudorules:
- name: "{{ item }}"
cmdcategory: all
hostgroup: "{{ item | lower }}"
host: "{{ item | lower }}.{{ ipa_domain }}"
group: "{{ item | lower }}"
user: "user{{ item | lower }}"
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure sudorule exist with members, uppercase
ipasudorule:
sudorules:
- name: "{{ item }}"
cmdcategory: all
hostgroup: "{{ item | upper }}"
host: "{{ item | upper }}.{{ ipa_domain }}"
group: "{{ item | upper }}"
user: "user{{ item | upper }}"
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure sudorule member is absent
ipasudorule:
sudorules:
- name: "{{ item }}"
hostgroup: "{{ item }}"
host: "{{ item }}.{{ ipa_domain }}"
group: "{{ item }}"
user: "user{{ item }}"
action: member
state: absent
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or not result.changed
- name: Ensure sudorule member is absent, lowercase
ipasudorule:
sudorules:
- name: "{{ item }}"
hostgroup: "{{ item | lower }}"
host: "{{ item | lower }}.{{ ipa_domain }}"
group: "{{ item | lower }}"
user: "user{{ item | lower }}"
action: member
state: absent
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure sudorule member is absent, upercase
ipasudorule:
sudorules:
- name: "{{ item }}"
hostgroup: "{{ item | upper }}"
host: "{{ item | upper }}.{{ ipa_domain }}"
group: "{{ item | upper }}"
user: "user{{ item | upper }}"
action: member
state: absent
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure sudorule member is present, upercase
ipasudorule:
sudorules:
- name: "{{ item }}"
hostgroup: "{{ item | upper }}"
host: "{{ item | upper }}.{{ ipa_domain }}"
group: "{{ item | upper }}"
user: "user{{ item | upper }}"
action: member
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or not result.changed
- name: Ensure sudorule member is present, lowercase
ipasudorule:
sudorules:
- name: "{{ item }}"
hostgroup: "{{ item | lower }}"
host: "{{ item | lower }}.{{ ipa_domain }}"
group: "{{ item | lower }}"
user: "user{{ item | lower }}"
action: member
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure sudorule member is present, mixed case
ipasudorule:
sudorules:
- name: "{{ item }}"
hostgroup: "{{ item }}"
host: "{{ item }}.{{ ipa_domain }}"
group: "{{ item }}"
user: "user{{ item }}"
action: member
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
# cleanup
always:
- name: Ensure sudorule do not exist
ipasudorule:
name: "{{ item }}"
state: absent
loop: "{{ groups_present }}"
- name: Ensure test groups do not exist.
ipagroup:
name: "{{ item }}"
state: absent
loop: "{{ groups_present }}"
- name: Ensure test hostgroups do not exist.
ipahostgroup:
name: "{{ item }}"
state: absent
loop: "{{ groups_present }}"
- name: Ensure test hosts do not exist.
ipahost:
name: "{{ item }}.{{ ipa_domain }}"
state: absent
loop: "{{ groups_present }}"
- name: Ensure test users do not exist.
ipauser:
name: "user{{ item }}"
state: absent
loop: "{{ groups_present }}"

View File

@@ -1,13 +0,0 @@
---
- name: Create users.json
hosts: localhost
tasks:
- name: Check if users.json exists
ansible.builtin.stat:
path: users.json
register: register_stat_users
- name: Create users.json
ansible.builtin.command: /bin/bash users.sh 500
when: not register_stat_users.stat.exists

View File

@@ -0,0 +1,48 @@
# Generate lists for users
---
- name: Create present services.json data
ansible.builtin.shell: |
date=$(date --date='+2 years' "+%Y-%m-%d %H:%M:%S")
echo "["
for i in $(seq -w 1 "{{ NUM }}"); do
echo " {"
echo " \"name\": \"testuser_${i}\","
echo " \"first\": \"First ${i}\","
echo " \"last\": \"Last ${i}\","
echo " \"password\": \"user${i}PW\","
echo " \"passwordexpiration\": \"${date}\""
if [ "$i" -lt "{{ NUM }}" ]; then
echo " },"
else
echo " }"
fi
done
echo "]"
vars:
NUM: 500
register: command
- name: Set user_list
ansible.builtin.set_fact:
user_list: "{{ command.stdout | from_json }}"
- name: Create absent user.json data
ansible.builtin.shell: |
echo "["
for i in $(seq -w 1 "{{ NUM }}"); do
echo " {"
echo " \"name\": \"testuser_${i}\""
if [ "$i" -lt "{{ NUM }}" ]; then
echo " },"
else
echo " }"
fi
done
echo "]"
vars:
NUM: 500
register: command
- name: Set user_absent_list
ansible.builtin.set_fact:
user_absent_list: "{{ command.stdout | from_json }}"

View File

@@ -1,24 +0,0 @@
---
- name: Include create_users_json.yml
ansible.builtin.import_playbook: create_users_json.yml
- name: Test users absent
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Include users.json
ansible.builtin.include_vars:
file: users.json # noqa missing-import
- name: Create dict with user names
ansible.builtin.set_fact:
user_names: "{{ user_names | default([]) + [{'name': item.name}] }}"
loop: "{{ users }}"
- name: Users absent len:{{ users | length }}
ipauser:
ipaadmin_password: SomeADMINpassword
users: "{{ user_names }}"
state: absent

View File

@@ -1,18 +0,0 @@
---
- name: Include create_users_json.yml
ansible.builtin.import_playbook: create_users_json.yml
- name: Test users present
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Include users.json
ansible.builtin.include_vars:
file: users.json # noqa missing-import
- name: Users present len:{{ users | length }}
ipauser:
ipaadmin_password: SomeADMINpassword
users: "{{ users }}"

View File

@@ -0,0 +1,38 @@
---
- name: Test users present and absent
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Include generate_test_data.yml
ansible.builtin.include_tasks: generate_test_data.yml
- name: Size of user_list
ansible.builtin.debug:
msg: "{{ user_list | length }}"
- name: Size of user_absent_list
ansible.builtin.debug:
msg: "{{ user_absent_list | length }}"
- name: Cleanup test users
ipauser:
ipaadmin_password: SomeADMINpassword
users: "{{ user_absent_list }}"
state: absent
- name: Users present
ipauser:
ipaadmin_password: SomeADMINpassword
users: "{{ user_list }}"
register: result
failed_when: not result.changed or result.failed
- name: Users absent
ipauser:
ipaadmin_password: SomeADMINpassword
users: "{{ user_absent_list }}"
state: absent
register: result
failed_when: not result.changed or result.failed

View File

@@ -0,0 +1,43 @@
---
- name: Test users present and absent with slice
hosts: ipaserver
become: true
gather_facts: false
vars:
slice_size: 100
tasks:
- name: Include generate_test_data.yml
ansible.builtin.include_tasks: generate_test_data.yml
- name: Size of user_list
ansible.builtin.debug:
msg: "{{ user_list | length }}"
- name: Size of user_absent_list
ansible.builtin.debug:
msg: "{{ user_absent_list | length }}"
- name: Cleanup test users
ipauser:
ipaadmin_password: SomeADMINpassword
users: "{{ user_absent_list[item : item + slice_size] }}"
state: absent
loop: "{{ range(0, user_absent_list | length, slice_size) | list }}"
- name: Users present
ipauser:
ipaadmin_password: SomeADMINpassword
users: "{{ user_list[item : item + slice_size] }}"
loop: "{{ range(0, user_list | length, slice_size) | list }}"
register: result
failed_when: not result.changed or result.failed
- name: Users absent
ipauser:
ipaadmin_password: SomeADMINpassword
users: "{{ user_absent_list[item : item + slice_size] }}"
state: absent
loop: "{{ range(0, user_absent_list | length, slice_size) | list }}"
register: result
failed_when: not result.changed or result.failed

View File

@@ -1,23 +0,0 @@
---
- name: Include create_users_json.yml
ansible.builtin.import_playbook: create_users_json.yml
- name: Test users present slice
hosts: ipaserver
become: true
gather_facts: false
vars:
slice_size: 500
tasks:
- name: Include users.json
ansible.builtin.include_vars:
file: users.json # noqa missing-import
- name: Size of users slice.
ansible.builtin.debug:
msg: "{{ users | length }}"
- name: Users present
ipauser:
ipaadmin_password: SomeADMINpassword
users: "{{ users[item : item + slice_size] }}"
loop: "{{ range(0, users | length, slice_size) | list }}"

View File

@@ -1,29 +0,0 @@
#!/bin/bash -eu
NUM=${1-1000}
FILE="users.json"
date=$(date --date='+2 years' "+%Y-%m-%d %H:%M:%S")
echo "{" > "$FILE"
echo " \"users\": [" >> "$FILE"
for i in $(seq 1 "$NUM"); do
{
echo " {"
echo " \"name\": \"user$i\","
echo " \"first\": \"First $i\","
echo " \"last\": \"Last $i\","
echo " \"password\": \"user${i}PW\","
echo " \"passwordexpiration\": \"$date\""
} >> "$FILE"
if [ "$i" -lt "$NUM" ]; then
echo " }," >> "$FILE"
else
echo " }" >> "$FILE"
fi
done
echo " ]" >> "$FILE"
echo "}" >> "$FILE"

View File

@@ -1,22 +0,0 @@
#!/bin/bash -eu
NUM=1000
FILE="users_absent.json"
echo "{" > "$FILE"
echo " \"users\": [" >> "$FILE"
for i in $(seq 1 "$NUM"); do
echo " {" >> "$FILE"
echo " \"name\": \"user$i\"," >> "$FILE"
if [ "$i" -lt "$NUM" ]; then
echo " }," >> "$FILE"
else
echo " }" >> "$FILE"
fi
done
echo " ]" >> "$FILE"
echo "}" >> "$FILE"

Some files were not shown because too many files have changed in this diff Show More