diff --git a/.config/ansible-lint.yml b/.config/ansible-lint.yml
new file mode 100644
index 0000000..7c92b22
--- /dev/null
+++ b/.config/ansible-lint.yml
@@ -0,0 +1,5 @@
+---
+profile: production
+exclude_paths:
+ - molecule
+ - tests/sanity
diff --git a/.github/patchback.yml b/.github/patchback.yml
new file mode 100644
index 0000000..113fc52
--- /dev/null
+++ b/.github/patchback.yml
@@ -0,0 +1,4 @@
+---
+backport_branch_prefix: patchback/backports/
+backport_label_prefix: backport-
+target_branch_prefix: stable-
diff --git a/.github/settings.yml b/.github/settings.yml
new file mode 100644
index 0000000..35f78e1
--- /dev/null
+++ b/.github/settings.yml
@@ -0,0 +1,6 @@
+---
+# DO NOT MODIFY
+
+# Settings: https://probot.github.io/apps/settings/
+# Pull settings from https://github.com/ansible-collections/.github/blob/master/.github/settings.yml
+_extends: ".github"
diff --git a/.github/stale.yml b/.github/stale.yml
new file mode 100644
index 0000000..230cf78
--- /dev/null
+++ b/.github/stale.yml
@@ -0,0 +1,60 @@
+---
+# Configuration for probot-stale - https://github.com/probot/stale
+
+# Number of days of inactivity before an Issue or Pull Request becomes stale
+daysUntilStale: 90
+
+# Number of days of inactivity before an Issue or Pull Request with the stale
+# label is closed. Set to false to disable. If disabled, issues still need to be
+# closed manually, but will remain marked as stale.
+daysUntilClose: 30
+
+# Only issues or pull requests with all of these labels are check if stale.
+# Defaults to `[]` (disabled)
+onlyLabels: []
+
+# Issues or Pull Requests with these labels will never be considered stale. Set
+# to `[]` to disable
+exemptLabels:
+ - security
+ - planned
+ - priority/critical
+ - lifecycle/frozen
+ - verified
+
+# Set to true to ignore issues in a project (defaults to false)
+exemptProjects: false
+
+# Set to true to ignore issues in a milestone (defaults to false)
+exemptMilestones: true
+
+# Set to true to ignore issues with an assignee (defaults to false)
+exemptAssignees: false
+
+# Label to use when marking as stale
+staleLabel: lifecycle/stale
+
+# Limit the number of actions per hour, from 1-30. Default is 30
+limitPerRun: 30
+
+pulls:
+ markComment: |-
+ PRs go stale after 90 days of inactivity.
+ If there is no further activity, the PR will be closed in another 30 days.
+
+ unmarkComment: >-
+ This pull request is no longer stale.
+
+ closeComment: >-
+ This pull request has been closed due to inactivity.
+
+issues:
+ markComment: |-
+ Issues go stale after 90 days of inactivity.
+ If there is no further activity, the issue will be closed in another 30 days.
+
+ unmarkComment: >-
+ This issue is no longer stale.
+
+ closeComment: >-
+ This issue has been closed due to inactivity.
diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml
new file mode 100644
index 0000000..569e334
--- /dev/null
+++ b/.github/workflows/changelog.yml
@@ -0,0 +1,23 @@
+---
+name: Changelog
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+on:
+ pull_request:
+ types:
+ - opened
+ - reopened
+ - labeled
+ - unlabeled
+ - synchronize
+ branches:
+ - main
+ - stable-*
+ tags:
+ - '*'
+
+jobs:
+ changelog:
+ uses: ansible-network/github_actions/.github/workflows/changelog.yml@main
diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml
new file mode 100644
index 0000000..11258aa
--- /dev/null
+++ b/.github/workflows/linters.yml
@@ -0,0 +1,29 @@
+---
+name: Linters
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+on:
+ pull_request:
+ types:
+ - opened
+ - reopened
+ - labeled
+ - unlabeled
+ - synchronize
+ branches:
+ - main
+ - stable-*
+ tags:
+ - '*'
+jobs:
+ linters:
+ uses: ansible-network/github_actions/.github/workflows/tox-linters.yml@main
+ ansible-lint:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: ansible-network/github_actions/.github/actions/checkout_dependency@main
+
+ - name: Run ansible-lint
+ uses: ansible/ansible-lint@v6.21.0
diff --git a/.github/workflows/sanity-tests.yml b/.github/workflows/sanity-tests.yml
new file mode 100644
index 0000000..49359de
--- /dev/null
+++ b/.github/workflows/sanity-tests.yml
@@ -0,0 +1,23 @@
+---
+name: Sanity tests
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+on:
+ pull_request:
+ types:
+ - opened
+ - reopened
+ - synchronize
+ branches:
+ - main
+ - stable-*
+ tags:
+ - '*'
+
+jobs:
+ sanity:
+ uses: ansible-network/github_actions/.github/workflows/sanity.yml@main
+ with:
+ collection_pre_install: '-r source/tests/sanity/requirements.yml'
diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml
new file mode 100644
index 0000000..d3aa3b0
--- /dev/null
+++ b/.github/workflows/unit-tests.yml
@@ -0,0 +1,21 @@
+---
+name: Unit tests
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+on:
+ pull_request:
+ types:
+ - opened
+ - reopened
+ - synchronize
+ branches:
+ - main
+ - stable-*
+ tags:
+ - '*'
+
+jobs:
+ unit-source:
+ uses: ansible-network/github_actions/.github/workflows/unit_source.yml@main
diff --git a/.yamllint b/.yamllint
index 8827676..ac5297c 100644
--- a/.yamllint
+++ b/.yamllint
@@ -1,33 +1,15 @@
---
-# Based on ansible-lint config
-extends: default
-
rules:
- braces:
- max-spaces-inside: 1
- level: error
- brackets:
- max-spaces-inside: 1
- level: error
- colons:
- max-spaces-after: -1
- level: error
- commas:
- max-spaces-after: -1
- level: error
- comments: disable
- comments-indentation: disable
- document-start: disable
- empty-lines:
- max: 3
- level: error
- hyphens:
- level: error
- indentation: disable
- key-duplicates: enable
- line-length: disable
- new-line-at-end-of-file: disable
- new-lines:
- type: unix
- trailing-spaces: disable
- truthy: disable
+ indentation:
+ ignore: &default_ignores |
+ # automatically generated, we can't control it
+ changelogs/changelog.yaml
+ # Will be gone when we release and automatically reformatted
+ changelogs/fragments/*
+ document-start:
+ ignore: *default_ignores
+ line-length:
+ ignore: *default_ignores
+ max: 160
+
+ignore-from-file: .gitignore
diff --git a/Makefile b/Makefile
index 7990f84..bb67bcc 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@ build: clean
ansible-galaxy collection build
install: build
- ansible-galaxy collection install -p ansible_collections community-okd-$(VERSION).tar.gz
+ ansible-galaxy collection install --force -p ansible_collections community-okd-$(VERSION).tar.gz
sanity: install
cd ansible_collections/community/okd && ansible-test sanity -v --python $(PYTHON_VERSION) $(SANITY_TEST_ARGS)
diff --git a/README.md b/README.md
index f3e1bba..45b63e9 100644
--- a/README.md
+++ b/README.md
@@ -10,13 +10,8 @@ The collection includes a variety of Ansible content to help automate the manage
## Ansible version compatibility
-This collection has been tested against following Ansible versions: **>=2.9.17**.
+This collection has been tested against following Ansible versions: **>=2.14.0**.
-For collections that support Ansible 2.9, please ensure you update your `network_os` to use the
-fully qualified collection name (for example, `cisco.ios.ios`).
-Plugins and modules within a collection may be tested with only specific Ansible versions.
-A collection may contain metadata that identifies these versions.
-PEP440 is the schema used to describe the versions of Ansible.
## Python Support
diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml
index 12184d7..cc99b46 100644
--- a/changelogs/changelog.yaml
+++ b/changelogs/changelog.yaml
@@ -1,201 +1,202 @@
+---
ancestor: null
releases:
0.1.0:
changes:
major_changes:
- - Add custom k8s module, integrate better Molecule tests (https://github.com/ansible-collections/community.okd/pull/7).
- - Add downstream build scripts to build redhat.openshift (https://github.com/ansible-collections/community.okd/pull/20).
- - Add openshift connection plugin, update inventory plugin to use it (https://github.com/ansible-collections/community.okd/pull/18).
- - Initial content migration from community.kubernetes (https://github.com/ansible-collections/community.okd/pull/3).
+ - Add custom k8s module, integrate better Molecule tests (https://github.com/ansible-collections/community.okd/pull/7).
+ - Add downstream build scripts to build redhat.openshift (https://github.com/ansible-collections/community.okd/pull/20).
+ - Add openshift connection plugin, update inventory plugin to use it (https://github.com/ansible-collections/community.okd/pull/18).
+ - Initial content migration from community.kubernetes (https://github.com/ansible-collections/community.okd/pull/3).
minor_changes:
- - Add incluster Makefile target for CI (https://github.com/ansible-collections/community.okd/pull/13).
- - Add tests for inventory plugin (https://github.com/ansible-collections/community.okd/pull/16).
- - CI Documentation for working with Prow (https://github.com/ansible-collections/community.okd/pull/15).
- - Docker container can run as an arbitrary user (https://github.com/ansible-collections/community.okd/pull/12).
- - Dockerfile now is properly set up to run tests in a rootless container (https://github.com/ansible-collections/community.okd/pull/11).
- - Integrate stale bot for issue queue maintenance (https://github.com/ansible-collections/community.okd/pull/14).
+ - Add incluster Makefile target for CI (https://github.com/ansible-collections/community.okd/pull/13).
+ - Add tests for inventory plugin (https://github.com/ansible-collections/community.okd/pull/16).
+ - CI Documentation for working with Prow (https://github.com/ansible-collections/community.okd/pull/15).
+ - Docker container can run as an arbitrary user (https://github.com/ansible-collections/community.okd/pull/12).
+ - Dockerfile now is properly set up to run tests in a rootless container (https://github.com/ansible-collections/community.okd/pull/11).
+ - Integrate stale bot for issue queue maintenance (https://github.com/ansible-collections/community.okd/pull/14).
fragments:
- - 1-initial-content.yml
- - 11-dockerfile-tests.yml
- - 12-dockerfile-tests.yml
- - 13-makefile-tests.yml
- - 15-ci-documentation.yml
- - 16-inventory-plugin-tests.yml
- - 18-openshift-connection-plugin.yml
- - 20-downstream-build-scripts.yml
- - 7-molecule-tests.yml
- - 8-stale-bot.yml
+ - 1-initial-content.yml
+ - 11-dockerfile-tests.yml
+ - 12-dockerfile-tests.yml
+ - 13-makefile-tests.yml
+ - 15-ci-documentation.yml
+ - 16-inventory-plugin-tests.yml
+ - 18-openshift-connection-plugin.yml
+ - 20-downstream-build-scripts.yml
+ - 7-molecule-tests.yml
+ - 8-stale-bot.yml
release_date: '2020-09-04'
0.2.0:
changes:
major_changes:
- - openshift_auth - new module (migrated from k8s_auth in community.kubernetes)
- (https://github.com/ansible-collections/community.okd/pull/33).
+ - openshift_auth - new module (migrated from k8s_auth in community.kubernetes)
+ (https://github.com/ansible-collections/community.okd/pull/33).
minor_changes:
- - Add a contribution guide (https://github.com/ansible-collections/community.okd/pull/37).
- - Use the API Group APIVersion for the `Route` object (https://github.com/ansible-collections/community.okd/pull/27).
+ - Add a contribution guide (https://github.com/ansible-collections/community.okd/pull/37).
+ - Use the API Group APIVersion for the `Route` object (https://github.com/ansible-collections/community.okd/pull/27).
fragments:
- - 27-route-api-group.yml
- - 33-add-k8s_auth.yml
- - 36-contribution-guide.yml
+ - 27-route-api-group.yml
+ - 33-add-k8s_auth.yml
+ - 36-contribution-guide.yml
modules:
- - description: Authenticate to OpenShift clusters which require an explicit login
- step
- name: openshift_auth
- namespace: ''
+ - description: Authenticate to OpenShift clusters which require an explicit login
+ step
+ name: openshift_auth
+ namespace: ''
release_date: '2020-09-24'
0.3.0:
changes:
major_changes:
- - Add openshift_process module for template rendering and optional application
- of rendered resources (https://github.com/ansible-collections/community.okd/pull/44).
- - Add openshift_route module for creating routes from services (https://github.com/ansible-collections/community.okd/pull/40).
+ - Add openshift_process module for template rendering and optional application
+ of rendered resources (https://github.com/ansible-collections/community.okd/pull/44).
+ - Add openshift_route module for creating routes from services (https://github.com/ansible-collections/community.okd/pull/40).
fragments:
- - 40-openshift_route.yml
- - 44-openshift_process.yml
+ - 40-openshift_route.yml
+ - 44-openshift_process.yml
modules:
- - description: Process an OpenShift template.openshift.io/v1 Template
- name: openshift_process
- namespace: ''
- - description: Expose a Service as an OpenShift Route.
- name: openshift_route
- namespace: ''
+ - description: Process an OpenShift template.openshift.io/v1 Template
+ name: openshift_process
+ namespace: ''
+ - description: Expose a Service as an OpenShift Route.
+ name: openshift_route
+ namespace: ''
release_date: '2020-10-12'
1.0.0:
changes:
minor_changes:
- - Released version 1 to Automation Hub as redhat.openshift (https://github.com/ansible-collections/community.okd/issues/51).
+ - Released version 1 to Automation Hub as redhat.openshift (https://github.com/ansible-collections/community.okd/issues/51).
fragments:
- - 51-redhat-openshift-ah-release.yml
+ - 51-redhat-openshift-ah-release.yml
release_date: '2020-11-12'
1.0.1:
changes:
bugfixes:
- - Generate downstream redhat.openshift documentation (https://github.com/ansible-collections/community.okd/pull/59).
+ - Generate downstream redhat.openshift documentation (https://github.com/ansible-collections/community.okd/pull/59).
fragments:
- - 59-downstream-docs.yml
+ - 59-downstream-docs.yml
release_date: '2020-11-17'
1.0.2:
changes:
minor_changes:
- - restrict the version of kubernetes.core dependency (https://github.com/ansible-collections/community.okd/pull/66).
+ - restrict the version of kubernetes.core dependency (https://github.com/ansible-collections/community.okd/pull/66).
fragments:
- - 66-restrict-kubernetes-core-version.yaml
+ - 66-restrict-kubernetes-core-version.yaml
release_date: '2021-02-19'
1.1.0:
changes:
minor_changes:
- - increase the kubernetes.core dependency version number (https://github.com/ansible-collections/community.okd/pull/71).
+ - increase the kubernetes.core dependency version number (https://github.com/ansible-collections/community.okd/pull/71).
fragments:
- - 71-bump-kubernetes-core-version.yaml
+ - 71-bump-kubernetes-core-version.yaml
release_date: '2021-02-23'
1.1.1:
changes:
bugfixes:
- - add missing requirements.txt file needed for execution environments (https://github.com/ansible-collections/community.okd/pull/78).
- - openshift_route - default to ``no_log=False`` for the ``key`` parameter in
- TLS configuration to fix sanity failures (https://github.com/ansible-collections/community.okd/pull/77).
- - restrict molecule version to <3.3.0 to address breaking change (https://github.com/ansible-collections/community.okd/pull/77).
- - update CI to work with ansible 2.11 (https://github.com/ansible-collections/community.okd/pull/80).
+ - add missing requirements.txt file needed for execution environments (https://github.com/ansible-collections/community.okd/pull/78).
+ - openshift_route - default to ``no_log=False`` for the ``key`` parameter in
+ TLS configuration to fix sanity failures (https://github.com/ansible-collections/community.okd/pull/77).
+ - restrict molecule version to <3.3.0 to address breaking change (https://github.com/ansible-collections/community.okd/pull/77).
+ - update CI to work with ansible 2.11 (https://github.com/ansible-collections/community.okd/pull/80).
fragments:
- - 77-fix-ci-failure.yaml
- - 78-add-requirements-file.yaml
- - 80-update-ci.yaml
+ - 77-fix-ci-failure.yaml
+ - 78-add-requirements-file.yaml
+ - 80-update-ci.yaml
release_date: '2021-04-06'
1.1.2:
changes:
bugfixes:
- - include requirements.txt in downstream build process (https://github.com/ansible-collections/community.okd/pull/81).
+ - include requirements.txt in downstream build process (https://github.com/ansible-collections/community.okd/pull/81).
fragments:
- - 81-include-requirements.yaml
+ - 81-include-requirements.yaml
release_date: '2021-04-08'
2.0.0:
changes:
breaking_changes:
- - drop python 2 support (https://github.com/openshift/community.okd/pull/93).
+ - drop python 2 support (https://github.com/openshift/community.okd/pull/93).
bugfixes:
- - fixes test suite to use correct versions of python and dependencies (https://github.com/ansible-collections/community.okd/pull/89).
- - openshift_process - fix module execution when template does not include a
- message (https://github.com/ansible-collections/community.okd/pull/87).
+ - fixes test suite to use correct versions of python and dependencies (https://github.com/ansible-collections/community.okd/pull/89).
+ - openshift_process - fix module execution when template does not include a
+ message (https://github.com/ansible-collections/community.okd/pull/87).
major_changes:
- - update to use kubernetes.core 2.0 (https://github.com/openshift/community.okd/pull/93).
+ - update to use kubernetes.core 2.0 (https://github.com/openshift/community.okd/pull/93).
minor_changes:
- - Added documentation for the ``community.okd`` collection.
- - openshift - inventory plugin supports FQCN ``redhat.openshift``.
+ - Added documentation for the ``community.okd`` collection.
+ - openshift - inventory plugin supports FQCN ``redhat.openshift``.
fragments:
- - 87-openshift_process-fix-template-without-message.yaml
- - 89-clean-up-ci.yaml
- - 93-update-to-k8s-2.yaml
- - add_docs.yml
- - fqcn_inventory.yml
+ - 87-openshift_process-fix-template-without-message.yaml
+ - 89-clean-up-ci.yaml
+ - 93-update-to-k8s-2.yaml
+ - add_docs.yml
+ - fqcn_inventory.yml
release_date: '2021-06-22'
2.0.1:
changes:
minor_changes:
- - increase kubernetes.core dependency version (https://github.com/openshift/community.okd/pull/97).
+ - increase kubernetes.core dependency version (https://github.com/openshift/community.okd/pull/97).
fragments:
- - 97-bump-k8s-version.yaml
+ - 97-bump-k8s-version.yaml
release_date: '2021-06-24'
2.1.0:
changes:
bugfixes:
- - fix broken links in Automation Hub for redhat.openshift (https://github.com/openshift/community.okd/issues/100).
+ - fix broken links in Automation Hub for redhat.openshift (https://github.com/openshift/community.okd/issues/100).
minor_changes:
- - add support for turbo mode (https://github.com/openshift/community.okd/pull/102).
- - openshift_route - Add support for Route annotations (https://github.com/ansible-collections/community.okd/pull/99).
+ - add support for turbo mode (https://github.com/openshift/community.okd/pull/102).
+ - openshift_route - Add support for Route annotations (https://github.com/ansible-collections/community.okd/pull/99).
fragments:
- - 0-copy_ignore_txt.yml
- - 100-fix-broken-links.yml
- - 102-support-turbo-mode.yaml
- - 99-openshift_route-add-support-for-annotations.yml
+ - 0-copy_ignore_txt.yml
+ - 100-fix-broken-links.yml
+ - 102-support-turbo-mode.yaml
+ - 99-openshift_route-add-support-for-annotations.yml
release_date: '2021-10-20'
2.2.0:
changes:
bugfixes:
- - fix ocp auth failing against cluster api url with trailing slash (https://github.com/openshift/community.okd/issues/139)
+ - fix ocp auth failing against cluster api url with trailing slash (https://github.com/openshift/community.okd/issues/139)
minor_changes:
- - add action groups to runtime.yml (https://github.com/openshift/community.okd/issues/41).
+ - add action groups to runtime.yml (https://github.com/openshift/community.okd/issues/41).
fragments:
- - 152-add-action-groups.yml
- - auth-against-api-with-trailing-slash.yaml
+ - 152-add-action-groups.yml
+ - auth-against-api-with-trailing-slash.yaml
modules:
- - description: Update TemplateInstances to point to the latest group-version-kinds
- name: openshift_adm_migrate_template_instances
- namespace: ''
- - description: Removes references to the specified roles, clusterroles, users,
- and groups
- name: openshift_adm_prune_auth
- namespace: ''
- - description: Remove old completed and failed deployment configs
- name: openshift_adm_prune_deployments
- namespace: ''
- - description: Remove unreferenced images
- name: openshift_adm_prune_images
- namespace: ''
- - description: Import the latest image information from a tag in a container image
- registry.
- name: openshift_import_image
- namespace: ''
- - description: Display information about the integrated registry.
- name: openshift_registry_info
- namespace: ''
+ - description: Update TemplateInstances to point to the latest group-version-kinds
+ name: openshift_adm_migrate_template_instances
+ namespace: ''
+ - description: Removes references to the specified roles, clusterroles, users,
+ and groups
+ name: openshift_adm_prune_auth
+ namespace: ''
+ - description: Remove old completed and failed deployment configs
+ name: openshift_adm_prune_deployments
+ namespace: ''
+ - description: Remove unreferenced images
+ name: openshift_adm_prune_images
+ namespace: ''
+ - description: Import the latest image information from a tag in a container image
+ registry.
+ name: openshift_import_image
+ namespace: ''
+ - description: Display information about the integrated registry.
+ name: openshift_registry_info
+ namespace: ''
release_date: '2022-05-05'
2.3.0:
changes:
bugfixes:
- - openshift_adm_groups_sync - initialize OpenshiftGroupSync attributes early
- to avoid Attribute error (https://github.com/openshift/community.okd/issues/155).
- - openshift_auth - Review the way the discard process is working, add openshift
- algorithm to convert token to resource object name (https://github.com/openshift/community.okd/issues/176).
+ - openshift_adm_groups_sync - initialize OpenshiftGroupSync attributes early
+ to avoid Attribute error (https://github.com/openshift/community.okd/issues/155).
+ - openshift_auth - Review the way the discard process is working, add openshift
+ algorithm to convert token to resource object name (https://github.com/openshift/community.okd/issues/176).
fragments:
- - 165-initialize-attributes-early.yml
- - 178-openshift_auth-fix-revoke-token.yml
- - 180-default-values-doc.yml
+ - 165-initialize-attributes-early.yml
+ - 178-openshift_auth-fix-revoke-token.yml
+ - 180-default-values-doc.yml
modules:
- - description: Prune old completed and failed builds
- name: openshift_adm_prune_builds
- namespace: ''
- - description: Start a new build or Cancel running, pending, or new builds.
- name: openshift_build
- namespace: ''
+ - description: Prune old completed and failed builds
+ name: openshift_adm_prune_builds
+ namespace: ''
+ - description: Start a new build or Cancel running, pending, or new builds.
+ name: openshift_build
+ namespace: ''
release_date: '2023-02-03'
diff --git a/changelogs/config.yaml b/changelogs/config.yaml
index 1a31c10..4e6bb5e 100644
--- a/changelogs/config.yaml
+++ b/changelogs/config.yaml
@@ -10,21 +10,21 @@ notesdir: fragments
prelude_section_name: release_summary
prelude_section_title: Release Summary
sections:
-- - major_changes
- - Major Changes
-- - minor_changes
- - Minor Changes
-- - breaking_changes
- - Breaking Changes / Porting Guide
-- - deprecated_features
- - Deprecated Features
-- - removed_features
- - Removed Features (previously deprecated)
-- - security_fixes
- - Security Fixes
-- - bugfixes
- - Bugfixes
-- - known_issues
- - Known Issues
+ - - major_changes
+ - Major Changes
+ - - minor_changes
+ - Minor Changes
+ - - breaking_changes
+ - Breaking Changes / Porting Guide
+ - - deprecated_features
+ - Deprecated Features
+ - - removed_features
+ - Removed Features (previously deprecated)
+ - - security_fixes
+ - Security Fixes
+ - - bugfixes
+ - Bugfixes
+ - - known_issues
+ - Known Issues
title: OKD Collection
trivial_section_name: trivial
diff --git a/changelogs/fragments/20230206-deprecate-openshift-inventory.yml b/changelogs/fragments/20230206-deprecate-openshift-inventory.yml
index efeb15a..4e41020 100644
--- a/changelogs/fragments/20230206-deprecate-openshift-inventory.yml
+++ b/changelogs/fragments/20230206-deprecate-openshift-inventory.yml
@@ -1,2 +1,4 @@
+---
deprecated_features:
-- openshift - the ``openshift`` inventory plugin has been deprecated and will be removed in release 4.0.0 (https://github.com/ansible-collections/kubernetes.core/issues/31).
+ - openshift - the ``openshift`` inventory plugin has been deprecated and will be removed in release 4.0.0
+ (https://github.com/ansible-collections/kubernetes.core/issues/31).
diff --git a/changelogs/fragments/20231107-move-sanity-and-units-to-gha.yml b/changelogs/fragments/20231107-move-sanity-and-units-to-gha.yml
new file mode 100644
index 0000000..29eaa48
--- /dev/null
+++ b/changelogs/fragments/20231107-move-sanity-and-units-to-gha.yml
@@ -0,0 +1,6 @@
+---
+trivial:
+ - "Move unit and sanity tests from zuul to GitHub Actions (https://github.com/openshift/community.okd/pull/202)."
+breaking_changes:
+ - "Remove support for ansible-core < 2.14 (https://github.com/openshift/community.okd/pull/202)."
+ - "Bump minimum Python suupported version to 3.9 (https://github.com/openshift/community.okd/pull/202)."
diff --git a/ci/Dockerfile b/ci/Dockerfile
index 1a50919..d57e7a0 100644
--- a/ci/Dockerfile
+++ b/ci/Dockerfile
@@ -1,4 +1,4 @@
-FROM registry.access.redhat.com/ubi8/ubi
+FROM registry.access.redhat.com/ubi9/ubi
ENV OPERATOR=/usr/local/bin/ansible-operator \
USER_UID=1001 \
@@ -11,20 +11,20 @@ RUN yum install -y \
glibc-langpack-en \
git \
make \
- python39 \
- python39-devel \
- python39-pip \
- python39-setuptools \
+ python3 \
+ python3-devel \
+ python3-pip \
+ python3-setuptools \
gcc \
openldap-devel \
- && pip3 install --no-cache-dir --upgrade setuptools pip \
- && pip3 install --no-cache-dir \
+ && python3.9 -m pip install --no-cache-dir --upgrade setuptools pip \
+ && python3.9 -m pip install --no-cache-dir \
kubernetes \
- ansible==2.9.* \
- "molecule<3.3.0" \
+ "ansible-core" \
+ "molecule" \
&& yum clean all \
&& rm -rf $HOME/.cache \
- && curl -L https://github.com/openshift/okd/releases/download/4.5.0-0.okd-2020-08-12-020541/openshift-client-linux-4.5.0-0.okd-2020-08-12-020541.tar.gz | tar -xz -C /usr/local/bin
+ && curl -L https://github.com/openshift/okd/releases/download/4.12.0-0.okd-2023-04-16-041331/openshift-client-linux-4.12.0-0.okd-2023-04-16-041331.tar.gz | tar -xz -C /usr/local/bin
# TODO: Is there a better way to install this client in ubi8?
COPY . /opt/ansible
diff --git a/ci/downstream.sh b/ci/downstream.sh
index 001959c..f2779e6 100755
--- a/ci/downstream.sh
+++ b/ci/downstream.sh
@@ -47,7 +47,7 @@ f_text_sub()
sed -i.bak "s/Kubernetes/OpenShift/g" "${_build_dir}/galaxy.yml"
sed -i.bak "s/^version\:.*$/version: ${DOWNSTREAM_VERSION}/" "${_build_dir}/galaxy.yml"
sed -i.bak "/STARTREMOVE/,/ENDREMOVE/d" "${_build_dir}/README.md"
- sed -i.bak "s/[[:space:]]okd:$/ openshift:/" ${_build_dir}/meta/runtime.yml
+ sed -i.bak "s/[[:space:]]okd:$/ openshift:/" "${_build_dir}/meta/runtime.yml"
find "${_build_dir}" -type f ! -name galaxy.yml -exec sed -i.bak "s/community\.okd/redhat\.openshift/g" {} \;
find "${_build_dir}" -type f -name "*.bak" -delete
@@ -67,7 +67,6 @@ f_prep()
LICENSE
README.md
Makefile
- setup.cfg
.yamllint
requirements.txt
requirements.yml
@@ -76,6 +75,7 @@ f_prep()
# Directories to recursively copy downstream (relative repo root dir path)
_dir_manifest=(
+ .config
changelogs
ci
meta
@@ -156,7 +156,7 @@ f_handle_doc_fragments_workaround()
# Build the collection, export docs, render them, stitch it all back together
pushd "${_build_dir}" || return
ansible-galaxy collection build
- ansible-galaxy collection install -p "${install_collections_dir}" ./*.tar.gz
+ ansible-galaxy collection install --force-with-deps -p "${install_collections_dir}" ./*.tar.gz
rm ./*.tar.gz
for doc_fragment_mod in "${_doc_fragment_modules[@]}"
do
diff --git a/meta/runtime.yml b/meta/runtime.yml
index 230d4fa..533a030 100644
--- a/meta/runtime.yml
+++ b/meta/runtime.yml
@@ -1,5 +1,5 @@
---
-requires_ansible: '>=2.9.17'
+requires_ansible: '>=2.14.0'
action_groups:
okd:
- k8s
diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml
index 7fe9e82..fb45006 100644
--- a/molecule/default/converge.yml
+++ b/molecule/default/converge.yml
@@ -21,16 +21,13 @@
debug:
var: output
- - name: Create deployment config
+ - name: Create deployment
community.okd.k8s:
state: present
name: hello-world
namespace: testing
definition: '{{ okd_dc_template }}'
wait: yes
- wait_condition:
- type: Available
- status: True
vars:
k8s_pod_name: hello-world
k8s_pod_image: python
@@ -71,19 +68,12 @@
namespace: '{{ namespace }}'
definition: '{{ okd_imagestream_template }}'
- - name: Create DeploymentConfig to reference ImageStream
- community.okd.k8s:
- name: '{{ k8s_pod_name }}'
- namespace: '{{ namespace }}'
- definition: '{{ okd_dc_template }}'
- vars:
- k8s_pod_name: is-idempotent-dc
-
- name: Create Deployment to reference ImageStream
community.okd.k8s:
name: '{{ k8s_pod_name }}'
namespace: '{{ namespace }}'
definition: '{{ k8s_deployment_template | combine(metadata) }}'
+ wait: true
vars:
k8s_pod_annotations:
"alpha.image.policy.openshift.io/resolve-names": "*"
diff --git a/molecule/default/files/pod-template.yaml b/molecule/default/files/pod-template.yaml
index ac388ad..3a1c8f1 100644
--- a/molecule/default/files/pod-template.yaml
+++ b/molecule/default/files/pod-template.yaml
@@ -10,14 +10,14 @@ objects:
name: "Pod-${{ NAME }}"
spec:
containers:
- - args:
- - /bin/sh
- - -c
- - while true; do echo $(date); sleep 15; done
- image: python:3.7-alpine
- imagePullPolicy: Always
- name: python
+ - args:
+ - /bin/sh
+ - -c
+ - while true; do echo $(date); sleep 15; done
+ image: python:3.7-alpine
+ imagePullPolicy: Always
+ name: python
parameters:
- - name: NAME
+ - name: NAME
description: trailing name of the pod
required: true
diff --git a/molecule/default/files/simple-template.yaml b/molecule/default/files/simple-template.yaml
index 29c85b9..c8270f7 100644
--- a/molecule/default/files/simple-template.yaml
+++ b/molecule/default/files/simple-template.yaml
@@ -13,22 +13,22 @@ metadata:
tags: quickstart,examples
name: simple-example
objects:
-- apiVersion: v1
- kind: ConfigMap
- metadata:
- annotations:
- description: Big example
- name: ${NAME}
- data:
- content: "${CONTENT}"
+ - apiVersion: v1
+ kind: ConfigMap
+ metadata:
+ annotations:
+ description: Big example
+ name: ${NAME}
+ data:
+ content: "${CONTENT}"
parameters:
-- description: The name assigned to the ConfigMap
- displayName: Name
- name: NAME
- required: true
- value: example
-- description: The value for the content key of the configmap
- displayName: Content
- name: CONTENT
- required: true
- value: ''
+ - description: The name assigned to the ConfigMap
+ displayName: Name
+ name: NAME
+ required: true
+ value: example
+ - description: The value for the content key of the configmap
+ displayName: Content
+ name: CONTENT
+ required: true
+ value: ''
diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml
index 43407bd..7ca7e2c 100644
--- a/molecule/default/molecule.yml
+++ b/molecule/default/molecule.yml
@@ -4,7 +4,7 @@ dependency:
options:
requirements-file: requirements.yml
driver:
- name: delegated
+ name: default
platforms:
- name: cluster
groups:
@@ -17,9 +17,6 @@ provisioner:
config_options:
inventory:
enable_plugins: community.okd.openshift
- lint: |
- set -e
- ansible-lint
inventory:
hosts:
plugin: community.okd.openshift
@@ -34,14 +31,10 @@ provisioner:
ANSIBLE_COLLECTIONS_PATHS: ${OVERRIDE_COLLECTION_PATH:-$MOLECULE_PROJECT_DIRECTORY}
verifier:
name: ansible
- lint: |
- set -e
- ansible-lint
scenario:
name: default
test_sequence:
- dependency
- - lint
- syntax
- prepare
- converge
diff --git a/molecule/default/prepare.yml b/molecule/default/prepare.yml
index f155ec1..0d0361a 100644
--- a/molecule/default/prepare.yml
+++ b/molecule/default/prepare.yml
@@ -37,12 +37,12 @@
name: cluster
spec:
identityProviders:
- - name: htpasswd_provider
- mappingMethod: claim
- type: HTPasswd
- htpasswd:
- fileData:
- name: htpass-secret
+ - name: htpasswd_provider
+ mappingMethod: claim
+ type: HTPasswd
+ htpasswd:
+ fileData:
+ name: htpass-secret
- name: Create ClusterRoleBinding for test user
community.okd.k8s:
diff --git a/molecule/default/roles/openshift_adm_groups/library/openshift_ldap_entry_info.py b/molecule/default/roles/openshift_adm_groups/library/openshift_ldap_entry_info.py
index ba49f72..c5bde3e 100644
--- a/molecule/default/roles/openshift_adm_groups/library/openshift_ldap_entry_info.py
+++ b/molecule/default/roles/openshift_adm_groups/library/openshift_ldap_entry_info.py
@@ -89,6 +89,7 @@ def execute():
ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
connection = ldap.initialize(module.params['server_uri'])
+ connection.set_option(ldap.OPT_REFERRALS, 0)
try:
connection.simple_bind_s(module.params['bind_dn'], module.params['bind_pw'])
except ldap.LDAPError as e:
diff --git a/molecule/default/roles/openshift_adm_groups/tasks/activeDirectory.yml b/molecule/default/roles/openshift_adm_groups/tasks/activeDirectory.yml
index da99f32..78131a8 100644
--- a/molecule/default/roles/openshift_adm_groups/tasks/activeDirectory.yml
+++ b/molecule/default/roles/openshift_adm_groups/tasks/activeDirectory.yml
@@ -1,227 +1,227 @@
+---
- block:
- - name: Get LDAP definition
- set_fact:
- ldap_entries: "{{ lookup('template', 'ad/definition.j2') | from_yaml }}"
+ - name: Get LDAP definition
+ set_fact:
+ ldap_entries: "{{ lookup('template', 'ad/definition.j2') | from_yaml }}"
- - name: Delete openshift groups if existing
- community.okd.k8s:
- state: absent
- kind: Group
- version: "user.openshift.io/v1"
- name: "{{ item }}"
- with_items:
- - admins
- - developers
-
- - name: Delete existing LDAP Entries
- openshift_ldap_entry:
- bind_dn: "{{ ldap_bind_dn }}"
- bind_pw: "{{ ldap_bind_pw }}"
- server_uri: "{{ ldap_server_uri }}"
- dn: "{{ item.dn }}"
- state: absent
- with_items: "{{ ldap_entries.users + ldap_entries.units | reverse | list }}"
-
- - name: Create LDAP Entries
- openshift_ldap_entry:
- bind_dn: "{{ ldap_bind_dn }}"
- bind_pw: "{{ ldap_bind_pw }}"
- server_uri: "{{ ldap_server_uri }}"
- dn: "{{ item.dn }}"
- attributes: "{{ item.attr }}"
- objectClass: "{{ item.class }}"
- with_items: "{{ ldap_entries.units + ldap_entries.users }}"
-
- - name: Load test configurations
- set_fact:
- sync_config: "{{ lookup('template', 'ad/sync-config.j2') | from_yaml }}"
-
- - name: Synchronize Groups
- community.okd.openshift_adm_groups_sync:
- config: "{{ sync_config }}"
- check_mode: yes
- register: result
-
- - name: Validate Group going to be created
- assert:
- that:
- - result is changed
- - admins_group
- - devs_group
- - '"jane.smith@ansible.org" in {{ admins_group.users }}'
- - '"jim.adams@ansible.org" in {{ admins_group.users }}'
- - '"jordanbulls@ansible.org" in {{ devs_group.users }}'
- - admins_group.users | length == 2
- - devs_group.users | length == 1
- vars:
- admins_group: "{{ result.groups | selectattr('metadata.name', 'equalto', 'admins') | first }}"
- devs_group: "{{ result.groups | selectattr('metadata.name', 'equalto', 'developers') | first }}"
-
-
- - name: Synchronize Groups (Remove check_mode)
- community.okd.openshift_adm_groups_sync:
- config: "{{ sync_config }}"
- register: result
-
- - name: Validate Group going to be created
- assert:
- that:
- - result is changed
-
- - name: Read admins group
- kubernetes.core.k8s_info:
- kind: Group
- version: "user.openshift.io/v1"
- name: admins
- register: result
-
- - name: Validate group was created
- assert:
- that:
- - result.resources | length == 1
- - '"jane.smith@ansible.org" in {{ result.resources.0.users }}'
- - '"jim.adams@ansible.org" in {{ result.resources.0.users }}'
-
- - name: Read developers group
- kubernetes.core.k8s_info:
- kind: Group
- version: "user.openshift.io/v1"
- name: developers
- register: result
-
- - name: Validate group was created
- assert:
- that:
- - result.resources | length == 1
- - '"jordanbulls@ansible.org" in {{ result.resources.0.users }}'
-
- - name: Define user dn to delete
- set_fact:
- user_to_delete: "cn=Jane,ou=engineers,ou=activeD,{{ ldap_root }}"
-
- - name: Delete 1 admin user
- openshift_ldap_entry:
- bind_dn: "{{ ldap_bind_dn }}"
- bind_pw: "{{ ldap_bind_pw }}"
- server_uri: "{{ ldap_server_uri }}"
- dn: "{{ user_to_delete }}"
- state: absent
-
- - name: Synchronize Openshift groups using allow_groups
- community.okd.openshift_adm_groups_sync:
- config: "{{ sync_config }}"
- allow_groups:
+ - name: Delete openshift groups if existing
+ community.okd.k8s:
+ state: absent
+ kind: Group
+ version: "user.openshift.io/v1"
+ name: "{{ item }}"
+ with_items:
+ - admins
- developers
- type: openshift
- register: openshift_sync
- - name: Validate that only developers group was sync
- assert:
- that:
- - openshift_sync is changed
- - openshift_sync.groups | length == 1
- - openshift_sync.groups.0.metadata.name == "developers"
+ - name: Delete existing LDAP Entries
+ openshift_ldap_entry:
+ bind_dn: "{{ ldap_bind_dn }}"
+ bind_pw: "{{ ldap_bind_pw }}"
+ server_uri: "{{ ldap_server_uri }}"
+ dn: "{{ item.dn }}"
+ state: absent
+ with_items: "{{ ldap_entries.users + ldap_entries.units | reverse | list }}"
- - name: Read admins group
- kubernetes.core.k8s_info:
- kind: Group
- version: "user.openshift.io/v1"
- name: admins
- register: result
+ - name: Create LDAP Entries
+ openshift_ldap_entry:
+ bind_dn: "{{ ldap_bind_dn }}"
+ bind_pw: "{{ ldap_bind_pw }}"
+ server_uri: "{{ ldap_server_uri }}"
+ dn: "{{ item.dn }}"
+ attributes: "{{ item.attr }}"
+ objectClass: "{{ item.class }}"
+ with_items: "{{ ldap_entries.units + ldap_entries.users }}"
- - name: Validate admins group content has not changed
- assert:
- that:
- - result.resources | length == 1
- - '"jane.smith@ansible.org" in {{ result.resources.0.users }}'
- - '"jim.adams@ansible.org" in {{ result.resources.0.users }}'
+ - name: Load test configurations
+ set_fact:
+ sync_config: "{{ lookup('template', 'ad/sync-config.j2') | from_yaml }}"
- - name: Synchronize Openshift groups using deny_groups
- community.okd.openshift_adm_groups_sync:
- config: "{{ sync_config }}"
- deny_groups:
- - developers
- type: openshift
- register: openshift_sync
+ - name: Synchronize Groups
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ sync_config }}"
+ check_mode: yes
+ register: result
- - name: Validate that only admins group was sync
- assert:
- that:
- - openshift_sync is changed
- - openshift_sync.groups | length == 1
- - openshift_sync.groups.0.metadata.name == "admins"
+ - name: Validate Group going to be created
+ assert:
+ that:
+ - result is changed
+ - admins_group
+ - devs_group
+ - '"jane.smith@ansible.org" in {{ admins_group.users }}'
+ - '"jim.adams@ansible.org" in {{ admins_group.users }}'
+ - '"jordanbulls@ansible.org" in {{ devs_group.users }}'
+ - admins_group.users | length == 2
+ - devs_group.users | length == 1
+ vars:
+ admins_group: "{{ result.groups | selectattr('metadata.name', 'equalto', 'admins') | first }}"
+ devs_group: "{{ result.groups | selectattr('metadata.name', 'equalto', 'developers') | first }}"
- - name: Read admins group
- kubernetes.core.k8s_info:
- kind: Group
- version: "user.openshift.io/v1"
- name: admins
- register: result
+ - name: Synchronize Groups (Remove check_mode)
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ sync_config }}"
+ register: result
- - name: Validate admins group contains only 1 user now
- assert:
- that:
- - result.resources | length == 1
- - result.resources.0.users == ["jim.adams@ansible.org"]
+ - name: Validate Group going to be created
+ assert:
+ that:
+ - result is changed
- - name: Set users to delete (delete all developers users)
- set_fact:
- user_to_delete: "cn=Jordan,ou=engineers,ou=activeD,{{ ldap_root }}"
+ - name: Read admins group
+ kubernetes.core.k8s_info:
+ kind: Group
+ version: "user.openshift.io/v1"
+ name: admins
+ register: result
- - name: Delete 1 admin user
- openshift_ldap_entry:
- bind_dn: "{{ ldap_bind_dn }}"
- bind_pw: "{{ ldap_bind_pw }}"
- server_uri: "{{ ldap_server_uri }}"
- dn: "{{ user_to_delete }}"
- state: absent
+ - name: Validate group was created
+ assert:
+ that:
+ - result.resources | length == 1
+ - '"jane.smith@ansible.org" in {{ result.resources.0.users }}'
+ - '"jim.adams@ansible.org" in {{ result.resources.0.users }}'
- - name: Prune groups
- community.okd.openshift_adm_groups_sync:
- config: "{{ sync_config }}"
- state: absent
- register: result
+ - name: Read developers group
+ kubernetes.core.k8s_info:
+ kind: Group
+ version: "user.openshift.io/v1"
+ name: developers
+ register: result
- - name: Validate result is changed (only developers group be deleted)
- assert:
- that:
- - result is changed
- - result.groups | length == 1
+ - name: Validate group was created
+ assert:
+ that:
+ - result.resources | length == 1
+ - '"jordanbulls@ansible.org" in {{ result.resources.0.users }}'
- - name: Get developers group info
- kubernetes.core.k8s_info:
- kind: Group
- version: "user.openshift.io/v1"
- name: developers
- register: result
+ - name: Define user dn to delete
+ set_fact:
+ user_to_delete: "cn=Jane,ou=engineers,ou=activeD,{{ ldap_root }}"
- - name: assert group was deleted
- assert:
- that:
- - result.resources | length == 0
+ - name: Delete 1 admin user
+ openshift_ldap_entry:
+ bind_dn: "{{ ldap_bind_dn }}"
+ bind_pw: "{{ ldap_bind_pw }}"
+ server_uri: "{{ ldap_server_uri }}"
+ dn: "{{ user_to_delete }}"
+ state: absent
- - name: Get admins group info
- kubernetes.core.k8s_info:
- kind: Group
- version: "user.openshift.io/v1"
- name: admins
- register: result
+ - name: Synchronize Openshift groups using allow_groups
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ sync_config }}"
+ allow_groups:
+ - developers
+ type: openshift
+ register: openshift_sync
- - name: assert group was not deleted
- assert:
- that:
- - result.resources | length == 1
+ - name: Validate that only developers group was sync
+ assert:
+ that:
+ - openshift_sync is changed
+ - openshift_sync.groups | length == 1
+ - openshift_sync.groups.0.metadata.name == "developers"
- - name: Prune groups once again (idempotency)
- community.okd.openshift_adm_groups_sync:
- config: "{{ sync_config }}"
- state: absent
- register: result
+ - name: Read admins group
+ kubernetes.core.k8s_info:
+ kind: Group
+ version: "user.openshift.io/v1"
+ name: admins
+ register: result
- - name: Assert nothing was changed
- assert:
- that:
- - result is not changed
+ - name: Validate admins group content has not changed
+ assert:
+ that:
+ - result.resources | length == 1
+ - '"jane.smith@ansible.org" in {{ result.resources.0.users }}'
+ - '"jim.adams@ansible.org" in {{ result.resources.0.users }}'
+
+ - name: Synchronize Openshift groups using deny_groups
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ sync_config }}"
+ deny_groups:
+ - developers
+ type: openshift
+ register: openshift_sync
+
+ - name: Validate that only admins group was sync
+ assert:
+ that:
+ - openshift_sync is changed
+ - openshift_sync.groups | length == 1
+ - openshift_sync.groups.0.metadata.name == "admins"
+
+ - name: Read admins group
+ kubernetes.core.k8s_info:
+ kind: Group
+ version: "user.openshift.io/v1"
+ name: admins
+ register: result
+
+ - name: Validate admins group contains only 1 user now
+ assert:
+ that:
+ - result.resources | length == 1
+ - result.resources.0.users == ["jim.adams@ansible.org"]
+
+ - name: Set users to delete (delete all developers users)
+ set_fact:
+ user_to_delete: "cn=Jordan,ou=engineers,ou=activeD,{{ ldap_root }}"
+
+ - name: Delete 1 admin user
+ openshift_ldap_entry:
+ bind_dn: "{{ ldap_bind_dn }}"
+ bind_pw: "{{ ldap_bind_pw }}"
+ server_uri: "{{ ldap_server_uri }}"
+ dn: "{{ user_to_delete }}"
+ state: absent
+
+ - name: Prune groups
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ sync_config }}"
+ state: absent
+ register: result
+
+ - name: Validate result is changed (only developers group be deleted)
+ assert:
+ that:
+ - result is changed
+ - result.groups | length == 1
+
+ - name: Get developers group info
+ kubernetes.core.k8s_info:
+ kind: Group
+ version: "user.openshift.io/v1"
+ name: developers
+ register: result
+
+ - name: assert group was deleted
+ assert:
+ that:
+ - result.resources | length == 0
+
+ - name: Get admins group info
+ kubernetes.core.k8s_info:
+ kind: Group
+ version: "user.openshift.io/v1"
+ name: admins
+ register: result
+
+ - name: assert group was not deleted
+ assert:
+ that:
+ - result.resources | length == 1
+
+ - name: Prune groups once again (idempotency)
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ sync_config }}"
+ state: absent
+ register: result
+
+ - name: Assert nothing was changed
+ assert:
+ that:
+ - result is not changed
always:
- name: Delete openshift groups if existing
diff --git a/molecule/default/roles/openshift_adm_groups/tasks/augmentedActiveDirectory.yml b/molecule/default/roles/openshift_adm_groups/tasks/augmentedActiveDirectory.yml
index f70d3bd..f089b33 100644
--- a/molecule/default/roles/openshift_adm_groups/tasks/augmentedActiveDirectory.yml
+++ b/molecule/default/roles/openshift_adm_groups/tasks/augmentedActiveDirectory.yml
@@ -1,166 +1,165 @@
+---
- block:
- - name: Get LDAP definition
- set_fact:
- ldap_entries: "{{ lookup('template', 'augmented-ad/definition.j2') | from_yaml }}"
+ - name: Get LDAP definition
+ set_fact:
+ ldap_entries: "{{ lookup('template', 'augmented-ad/definition.j2') | from_yaml }}"
- - name: Delete openshift groups if existing
- community.okd.k8s:
- state: absent
- kind: Group
- version: "user.openshift.io/v1"
- name: "{{ item }}"
- with_items:
- - banking
- - insurance
+ - name: Delete openshift groups if existing
+ community.okd.k8s:
+ state: absent
+ kind: Group
+ version: "user.openshift.io/v1"
+ name: "{{ item }}"
+ with_items:
+ - banking
+ - insurance
- - name: Delete existing LDAP entries
- openshift_ldap_entry:
- bind_dn: "{{ ldap_bind_dn }}"
- bind_pw: "{{ ldap_bind_pw }}"
- server_uri: "{{ ldap_server_uri }}"
- dn: "{{ item.dn }}"
- state: absent
- with_items: "{{ ldap_entries.users + ldap_entries.groups + ldap_entries.units | reverse | list }}"
+ - name: Delete existing LDAP entries
+ openshift_ldap_entry:
+ bind_dn: "{{ ldap_bind_dn }}"
+ bind_pw: "{{ ldap_bind_pw }}"
+ server_uri: "{{ ldap_server_uri }}"
+ dn: "{{ item.dn }}"
+ state: absent
+ with_items: "{{ ldap_entries.users + ldap_entries.groups + ldap_entries.units | reverse | list }}"
- - name: Create LDAP Entries
- openshift_ldap_entry:
- bind_dn: "{{ ldap_bind_dn }}"
- bind_pw: "{{ ldap_bind_pw }}"
- server_uri: "{{ ldap_server_uri }}"
- dn: "{{ item.dn }}"
- attributes: "{{ item.attr }}"
- objectClass: "{{ item.class }}"
- with_items: "{{ ldap_entries.units + ldap_entries.groups + ldap_entries.users }}"
+ - name: Create LDAP Entries
+ openshift_ldap_entry:
+ bind_dn: "{{ ldap_bind_dn }}"
+ bind_pw: "{{ ldap_bind_pw }}"
+ server_uri: "{{ ldap_server_uri }}"
+ dn: "{{ item.dn }}"
+ attributes: "{{ item.attr }}"
+ objectClass: "{{ item.class }}"
+ with_items: "{{ ldap_entries.units + ldap_entries.groups + ldap_entries.users }}"
- - name: Load test configurations
- set_fact:
- sync_config: "{{ lookup('template', 'augmented-ad/sync-config.j2') | from_yaml }}"
+ - name: Load test configurations
+ set_fact:
+ sync_config: "{{ lookup('template', 'augmented-ad/sync-config.j2') | from_yaml }}"
- - name: Synchronize Groups
- community.okd.openshift_adm_groups_sync:
- config: "{{ sync_config }}"
- check_mode: yes
- register: result
+ - name: Synchronize Groups
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ sync_config }}"
+ check_mode: yes
+ register: result
- - name: Validate that 'banking' and 'insurance' groups were created
- assert:
- that:
- - result is changed
- - banking_group
- - insurance_group
- - '"james-allan@ansible.org" in {{ banking_group.users }}'
- - '"gordon-kane@ansible.org" in {{ banking_group.users }}'
- - '"alice-courtney@ansible.org" in {{ insurance_group.users }}'
- - banking_group.users | length == 2
- - insurance_group.users | length == 1
- vars:
- banking_group: "{{ result.groups | selectattr('metadata.name', 'equalto', 'banking') | first }}"
- insurance_group: "{{ result.groups | selectattr('metadata.name', 'equalto', 'insurance') | first }}"
+ - name: Validate that 'banking' and 'insurance' groups were created
+ assert:
+ that:
+ - result is changed
+ - banking_group
+ - insurance_group
+ - '"james-allan@ansible.org" in {{ banking_group.users }}'
+ - '"gordon-kane@ansible.org" in {{ banking_group.users }}'
+ - '"alice-courtney@ansible.org" in {{ insurance_group.users }}'
+ - banking_group.users | length == 2
+ - insurance_group.users | length == 1
+ vars:
+ banking_group: "{{ result.groups | selectattr('metadata.name', 'equalto', 'banking') | first }}"
+ insurance_group: "{{ result.groups | selectattr('metadata.name', 'equalto', 'insurance') | first }}"
+ - name: Synchronize Groups (Remove check_mode)
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ sync_config }}"
+ register: result
- - name: Synchronize Groups (Remove check_mode)
- community.okd.openshift_adm_groups_sync:
- config: "{{ sync_config }}"
- register: result
+ - name: Validate Group going to be created
+ assert:
+ that:
+ - result is changed
- - name: Validate Group going to be created
- assert:
- that:
- - result is changed
+ - name: Define facts for group to create
+ set_fact:
+ ldap_groups:
+ - name: banking
+ users:
+ - "james-allan@ansible.org"
+ - "gordon-kane@ansible.org"
+ - name: insurance
+ users:
+ - "alice-courtney@ansible.org"
- - name: Define facts for group to create
- set_fact:
- ldap_groups:
- - name: banking
- users:
- - "james-allan@ansible.org"
- - "gordon-kane@ansible.org"
- - name: insurance
- users:
- - "alice-courtney@ansible.org"
+ - name: Read 'banking' openshift group
+ kubernetes.core.k8s_info:
+ kind: Group
+ version: "user.openshift.io/v1"
+ name: banking
+ register: result
+ - name: Validate group info
+ assert:
+ that:
+ - result.resources | length == 1
+ - '"james-allan@ansible.org" in {{ result.resources.0.users }}'
+ - '"gordon-kane@ansible.org" in {{ result.resources.0.users }}'
- - name: Read 'banking' openshift group
- kubernetes.core.k8s_info:
- kind: Group
- version: "user.openshift.io/v1"
- name: banking
- register: result
+ - name: Read 'insurance' openshift group
+ kubernetes.core.k8s_info:
+ kind: Group
+ version: "user.openshift.io/v1"
+ name: insurance
+ register: result
- - name: Validate group info
- assert:
- that:
- - result.resources | length == 1
- - '"james-allan@ansible.org" in {{ result.resources.0.users }}'
- - '"gordon-kane@ansible.org" in {{ result.resources.0.users }}'
+ - name: Validate group info
+ assert:
+ that:
+ - result.resources | length == 1
+ - 'result.resources.0.users == ["alice-courtney@ansible.org"]'
- - name: Read 'insurance' openshift group
- kubernetes.core.k8s_info:
- kind: Group
- version: "user.openshift.io/v1"
- name: insurance
- register: result
+ - name: Delete employee from 'insurance' group
+ openshift_ldap_entry:
+ bind_dn: "{{ ldap_bind_dn }}"
+ bind_pw: "{{ ldap_bind_pw }}"
+ server_uri: "{{ ldap_server_uri }}"
+ dn: "cn=Alice,ou=employee,ou=augmentedAD,{{ ldap_root }}"
+ state: absent
- - name: Validate group info
- assert:
- that:
- - result.resources | length == 1
- - 'result.resources.0.users == ["alice-courtney@ansible.org"]'
+ - name: Prune groups
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ sync_config }}"
+ state: absent
+ register: result
- - name: Delete employee from 'insurance' group
- openshift_ldap_entry:
- bind_dn: "{{ ldap_bind_dn }}"
- bind_pw: "{{ ldap_bind_pw }}"
- server_uri: "{{ ldap_server_uri }}"
- dn: "cn=Alice,ou=employee,ou=augmentedAD,{{ ldap_root }}"
- state: absent
+ - name: Validate result is changed (only insurance group be deleted)
+ assert:
+ that:
+ - result is changed
+ - result.groups | length == 1
- - name: Prune groups
- community.okd.openshift_adm_groups_sync:
- config: "{{ sync_config }}"
- state: absent
- register: result
+ - name: Get 'insurance' openshift group info
+ kubernetes.core.k8s_info:
+ kind: Group
+ version: "user.openshift.io/v1"
+ name: insurance
+ register: result
- - name: Validate result is changed (only insurance group be deleted)
- assert:
- that:
- - result is changed
- - result.groups | length == 1
+ - name: assert group was deleted
+ assert:
+ that:
+ - result.resources | length == 0
- - name: Get 'insurance' openshift group info
- kubernetes.core.k8s_info:
- kind: Group
- version: "user.openshift.io/v1"
- name: insurance
- register: result
+ - name: Get 'banking' openshift group info
+ kubernetes.core.k8s_info:
+ kind: Group
+ version: "user.openshift.io/v1"
+ name: banking
+ register: result
- - name: assert group was deleted
- assert:
- that:
- - result.resources | length == 0
+ - name: assert group was not deleted
+ assert:
+ that:
+ - result.resources | length == 1
- - name: Get 'banking' openshift group info
- kubernetes.core.k8s_info:
- kind: Group
- version: "user.openshift.io/v1"
- name: banking
- register: result
+ - name: Prune groups once again (idempotency)
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ sync_config }}"
+ state: absent
+ register: result
- - name: assert group was not deleted
- assert:
- that:
- - result.resources | length == 1
-
- - name: Prune groups once again (idempotency)
- community.okd.openshift_adm_groups_sync:
- config: "{{ sync_config }}"
- state: absent
- register: result
-
- - name: Assert no change was made
- assert:
- that:
- - result is not changed
+ - name: Assert no change was made
+ assert:
+ that:
+ - result is not changed
always:
- name: Delete openshift groups if existing
diff --git a/molecule/default/roles/openshift_adm_groups/tasks/main.yml b/molecule/default/roles/openshift_adm_groups/tasks/main.yml
index 88bfd67..5dc79c1 100644
--- a/molecule/default/roles/openshift_adm_groups/tasks/main.yml
+++ b/molecule/default/roles/openshift_adm_groups/tasks/main.yml
@@ -1,5 +1,5 @@
---
-- name: Get cluster information
+- name: Get cluster information
kubernetes.core.k8s_cluster_info:
register: info
@@ -16,30 +16,29 @@
app: ldap
spec:
containers:
- - name: ldap
- image: bitnami/openldap
- env:
- - name: LDAP_ADMIN_USERNAME
- value: "{{ ldap_admin_user }}"
- - name: LDAP_ADMIN_PASSWORD
- value: "{{ ldap_admin_password }}"
- - name: LDAP_USERS
- value: "ansible"
- - name: LDAP_PASSWORDS
- value: "ansible123"
- - name: LDAP_ROOT
- value: "{{ ldap_root }}"
- ports:
- - containerPort: 1389
+ - name: ldap
+ image: bitnami/openldap
+ env:
+ - name: LDAP_ADMIN_USERNAME
+ value: "{{ ldap_admin_user }}"
+ - name: LDAP_ADMIN_PASSWORD
+ value: "{{ ldap_admin_password }}"
+ - name: LDAP_USERS
+ value: "ansible"
+ - name: LDAP_PASSWORDS
+ value: "ansible123"
+ - name: LDAP_ROOT
+ value: "{{ ldap_root }}"
+ ports:
+ - containerPort: 1389
+ name: ldap-server
register: pod_info
-- name: Set Pod Internal IP
- set_fact:
- podIp: "{{ pod_info.result.status.podIP }}"
-
- name: Set LDAP Common facts
set_fact:
- ldap_server_uri: "ldap://{{ podIp }}:1389"
+ # we can use the Pod IP directly because the integration are running inside a Pod in the
+ # same openshift cluster
+ ldap_server_uri: "ldap://{{ pod_info.result.status.podIP }}:1389"
ldap_bind_dn: "cn={{ ldap_admin_user }},{{ ldap_root }}"
ldap_bind_pw: "{{ ldap_admin_password }}"
@@ -53,8 +52,10 @@
bind_pw: "{{ ldap_bind_pw }}"
dn: "ou=users,{{ ldap_root }}"
server_uri: "{{ ldap_server_uri }}"
- # ignore_errors: true
- # register: ping_ldap
+ register: test_ldap
+ retries: 10
+ delay: 5
+ until: test_ldap is not failed
- include_tasks: "tasks/python-ldap-not-installed.yml"
- include_tasks: "tasks/rfc2307.yml"
diff --git a/molecule/default/roles/openshift_adm_groups/tasks/python-ldap-not-installed.yml b/molecule/default/roles/openshift_adm_groups/tasks/python-ldap-not-installed.yml
index a79af51..857ff49 100644
--- a/molecule/default/roles/openshift_adm_groups/tasks/python-ldap-not-installed.yml
+++ b/molecule/default/roles/openshift_adm_groups/tasks/python-ldap-not-installed.yml
@@ -1,3 +1,4 @@
+---
- block:
- name: Create temp directory
tempfile:
diff --git a/molecule/default/roles/openshift_adm_groups/tasks/rfc2307.yml b/molecule/default/roles/openshift_adm_groups/tasks/rfc2307.yml
index 7660bf6..749dfda 100644
--- a/molecule/default/roles/openshift_adm_groups/tasks/rfc2307.yml
+++ b/molecule/default/roles/openshift_adm_groups/tasks/rfc2307.yml
@@ -1,459 +1,460 @@
+---
- block:
- - name: Get LDAP definition
- set_fact:
- ldap_resources: "{{ lookup('template', 'rfc2307/definition.j2') | from_yaml }}"
+ - name: Get LDAP definition
+ set_fact:
+ ldap_resources: "{{ lookup('template', 'rfc2307/definition.j2') | from_yaml }}"
- - name: Delete openshift groups if existing
- community.okd.k8s:
- state: absent
- kind: Group
- version: "user.openshift.io/v1"
- name: "{{ item }}"
- with_items:
- - admins
- - engineers
- - developers
-
- - name: Delete existing LDAP entries
- openshift_ldap_entry:
- bind_dn: "{{ ldap_bind_dn }}"
- bind_pw: "{{ ldap_bind_pw }}"
- server_uri: "{{ ldap_server_uri }}"
- dn: "{{ item.dn }}"
- state: absent
- with_items: "{{ ldap_resources.users + ldap_resources.groups + ldap_resources.units | reverse | list }}"
-
- - name: Create LDAP units
- openshift_ldap_entry:
- bind_dn: "{{ ldap_bind_dn }}"
- bind_pw: "{{ ldap_bind_pw }}"
- server_uri: "{{ ldap_server_uri }}"
- dn: "{{ item.dn }}"
- attributes: "{{ item.attr }}"
- objectClass: "{{ item.class }}"
- with_items: "{{ ldap_resources.units }}"
-
- - name: Create LDAP Groups
- openshift_ldap_entry:
- bind_dn: "{{ ldap_bind_dn }}"
- bind_pw: "{{ ldap_bind_pw }}"
- server_uri: "{{ ldap_server_uri }}"
- dn: "{{ item.dn }}"
- attributes: "{{ item.attr }}"
- objectClass: "{{ item.class }}"
- with_items: "{{ ldap_resources.groups }}"
-
- - name: Create LDAP users
- openshift_ldap_entry:
- bind_dn: "{{ ldap_bind_dn }}"
- bind_pw: "{{ ldap_bind_pw }}"
- server_uri: "{{ ldap_server_uri }}"
- dn: "{{ item.dn }}"
- attributes: "{{ item.attr }}"
- objectClass: "{{ item.class }}"
- with_items: "{{ ldap_resources.users }}"
-
- - name: Load test configurations
- set_fact:
- configs: "{{ lookup('template', 'rfc2307/sync-config.j2') | from_yaml }}"
-
- - name: Synchronize Groups
- community.okd.openshift_adm_groups_sync:
- config: "{{ configs.simple }}"
- check_mode: yes
- register: result
-
- - name: Validate Group going to be created
- assert:
- that:
- - result is changed
- - admins_group
- - devs_group
- - '"jane.smith@ansible.org" in {{ admins_group.users }}'
- - '"jim.adams@ansible.org" in {{ devs_group.users }}'
- - '"jordanbulls@ansible.org" in {{ devs_group.users }}'
- - admins_group.users | length == 1
- - devs_group.users | length == 2
- vars:
- admins_group: "{{ result.groups | selectattr('metadata.name', 'equalto', 'admins') | first }}"
- devs_group: "{{ result.groups | selectattr('metadata.name', 'equalto', 'developers') | first }}"
-
- - name: Synchronize Groups - User defined mapping
- community.okd.openshift_adm_groups_sync:
- config: "{{ configs.user_defined }}"
- check_mode: yes
- register: result
-
- - name: Validate Group going to be created
- assert:
- that:
- - result is changed
- - admins_group
- - devs_group
- - '"jane.smith@ansible.org" in {{ admins_group.users }}'
- - '"jim.adams@ansible.org" in {{ devs_group.users }}'
- - '"jordanbulls@ansible.org" in {{ devs_group.users }}'
- - admins_group.users | length == 1
- - devs_group.users | length == 2
- vars:
- admins_group: "{{ result.groups | selectattr('metadata.name', 'equalto', 'ansible-admins') | first }}"
- devs_group: "{{ result.groups | selectattr('metadata.name', 'equalto', 'ansible-devs') | first }}"
-
- - name: Synchronize Groups - Using dn for every query
- community.okd.openshift_adm_groups_sync:
- config: "{{ configs.dn_everywhere }}"
- check_mode: yes
- register: result
-
- - name: Validate Group going to be created
- assert:
- that:
- - result is changed
- - admins_group
- - devs_group
- - '"cn=Jane,ou=people,ou=rfc2307,{{ ldap_root }}" in {{ admins_group.users }}'
- - '"cn=Jim,ou=people,ou=rfc2307,{{ ldap_root }}" in {{ devs_group.users }}'
- - '"cn=Jordan,ou=people,ou=rfc2307,{{ ldap_root }}" in {{ devs_group.users }}'
- - admins_group.users | length == 1
- - devs_group.users | length == 2
- vars:
- admins_group: "{{ result.groups | selectattr('metadata.name', 'equalto', 'cn=admins,ou=groups,ou=rfc2307,' + ldap_root ) | first }}"
- devs_group: "{{ result.groups | selectattr('metadata.name', 'equalto', 'cn=developers,ou=groups,ou=rfc2307,' + ldap_root ) | first }}"
-
- - name: Synchronize Groups - Partially user defined mapping
- community.okd.openshift_adm_groups_sync:
- config: "{{ configs.partially_user_defined }}"
- check_mode: yes
- register: result
-
- - name: Validate Group going to be created
- assert:
- that:
- - result is changed
- - admins_group
- - devs_group
- - '"jane.smith@ansible.org" in {{ admins_group.users }}'
- - '"jim.adams@ansible.org" in {{ devs_group.users }}'
- - '"jordanbulls@ansible.org" in {{ devs_group.users }}'
- - admins_group.users | length == 1
- - devs_group.users | length == 2
- vars:
- admins_group: "{{ result.groups | selectattr('metadata.name', 'equalto', 'ansible-admins') | first }}"
- devs_group: "{{ result.groups | selectattr('metadata.name', 'equalto', 'developers') | first }}"
-
- - name: Delete Group 'engineers' if created before
- community.okd.k8s:
- state: absent
- kind: Group
- version: "user.openshift.io/v1"
- name: 'engineers'
- wait: yes
- ignore_errors: yes
-
- - name: Synchronize Groups - Partially user defined mapping
- community.okd.openshift_adm_groups_sync:
- config: "{{ configs.out_scope }}"
- check_mode: yes
- register: result
- ignore_errors: yes
-
- - name: Assert group sync failed due to non-existent member
- assert:
- that:
- - result is failed
- - result.msg.startswith("Entry not found for base='cn=Matthew,ou=people,ou=outrfc2307,{{ ldap_root }}'")
-
- - name: Define sync configuration with tolerateMemberNotFoundErrors
- set_fact:
- config_out_of_scope_tolerate_not_found: "{{ configs.out_scope | combine({'rfc2307': merge_rfc2307 })}}"
- vars:
- merge_rfc2307: "{{ configs.out_scope.rfc2307 | combine({'tolerateMemberNotFoundErrors': 'true'}) }}"
-
- - name: Synchronize Groups - Partially user defined mapping (tolerateMemberNotFoundErrors=true)
- community.okd.openshift_adm_groups_sync:
- config: "{{ config_out_of_scope_tolerate_not_found }}"
- check_mode: yes
- register: result
-
- - name: Assert group sync did not fail (tolerateMemberNotFoundErrors=true)
- assert:
- that:
- - result is changed
- - result.groups | length == 1
- - result.groups.0.metadata.name == 'engineers'
- - result.groups.0.users == ['Abraham']
-
- - name: Create Group 'engineers'
- community.okd.k8s:
- state: present
- wait: yes
- definition:
+ - name: Delete openshift groups if existing
+ community.okd.k8s:
+ state: absent
kind: Group
- apiVersion: "user.openshift.io/v1"
- metadata:
- name: engineers
- users: []
-
- - name: Try to sync LDAP group with Openshift existing group not created using sync should failed
- community.okd.openshift_adm_groups_sync:
- config: "{{ config_out_of_scope_tolerate_not_found }}"
- check_mode: yes
- register: result
- ignore_errors: yes
-
- - name: Validate group sync failed
- assert:
- that:
- - result is failed
- - '"openshift.io/ldap.host label did not match sync host" in result.msg'
-
- - name: Define allow_groups and deny_groups groups
- set_fact:
- allow_groups:
- - "cn=developers,ou=groups,ou=rfc2307,{{ ldap_root }}"
- deny_groups:
- - "cn=admins,ou=groups,ou=rfc2307,{{ ldap_root }}"
-
- - name: Synchronize Groups using allow_groups
- community.okd.openshift_adm_groups_sync:
- config: "{{ configs.simple }}"
- allow_groups: "{{ allow_groups }}"
- register: result
- check_mode: yes
-
- - name: Validate Group going to be created
- assert:
- that:
- - result is changed
- - result.groups | length == 1
- - result.groups.0.metadata.name == "developers"
-
- - name: Synchronize Groups using deny_groups
- community.okd.openshift_adm_groups_sync:
- config: "{{ configs.simple }}"
- deny_groups: "{{ deny_groups }}"
- register: result
- check_mode: yes
-
- - name: Validate Group going to be created
- assert:
- that:
- - result is changed
- - result.groups | length == 1
- - result.groups.0.metadata.name == "developers"
-
- - name: Synchronize groups, remove check_mode
- community.okd.openshift_adm_groups_sync:
- config: "{{ configs.simple }}"
- register: result
-
- - name: Validate result is changed
- assert:
- that:
- - result is changed
-
- - name: Read Groups
- kubernetes.core.k8s_info:
- kind: Group
- version: "user.openshift.io/v1"
- name: admins
- register: result
-
- - name: Validate group was created
- assert:
- that:
- - result.resources | length == 1
- - '"jane.smith@ansible.org" in {{ result.resources.0.users }}'
-
- - name: Read Groups
- kubernetes.core.k8s_info:
- kind: Group
- version: "user.openshift.io/v1"
- name: developers
- register: result
-
- - name: Validate group was created
- assert:
- that:
- - result.resources | length == 1
- - '"jim.adams@ansible.org" in {{ result.resources.0.users }}'
- - '"jordanbulls@ansible.org" in {{ result.resources.0.users }}'
-
- - name: Set users to delete (no admins users anymore and only 1 developer kept)
- set_fact:
- users_to_delete:
- - "cn=Jane,ou=people,ou=rfc2307,{{ ldap_root }}"
- - "cn=Jim,ou=people,ou=rfc2307,{{ ldap_root }}"
-
- - name: Delete users from LDAP servers
- openshift_ldap_entry:
- bind_dn: "{{ ldap_bind_dn }}"
- bind_pw: "{{ ldap_bind_pw }}"
- server_uri: "{{ ldap_server_uri }}"
- dn: "{{ item }}"
- state: absent
- with_items: "{{ users_to_delete }}"
-
- - name: Define sync configuration with tolerateMemberNotFoundErrors
- set_fact:
- config_simple_tolerate_not_found: "{{ configs.simple | combine({'rfc2307': merge_rfc2307 })}}"
- vars:
- merge_rfc2307: "{{ configs.simple.rfc2307 | combine({'tolerateMemberNotFoundErrors': 'true'}) }}"
-
- - name: Synchronize groups once again after users deletion
- community.okd.openshift_adm_groups_sync:
- config: "{{ config_simple_tolerate_not_found }}"
- register: result
-
- - name: Validate result is changed
- assert:
- that:
- - result is changed
-
- - name: Read Groups
- kubernetes.core.k8s_info:
- kind: Group
- version: "user.openshift.io/v1"
- name: admins
- register: result
-
- - name: Validate admins group does not contains users anymore
- assert:
- that:
- - result.resources | length == 1
- - result.resources.0.users == []
-
- - name: Read Groups
- kubernetes.core.k8s_info:
- kind: Group
- version: "user.openshift.io/v1"
- name: developers
- register: result
-
- - name: Validate group was created
- assert:
- that:
- - result.resources | length == 1
- - '"jordanbulls@ansible.org" in {{ result.resources.0.users }}'
-
- - name: Set group to delete
- set_fact:
- groups_to_delete:
- - "cn=developers,ou=groups,ou=rfc2307,{{ ldap_root }}"
-
- - name: Delete Group from LDAP servers
- openshift_ldap_entry:
- bind_dn: "{{ ldap_bind_dn }}"
- bind_pw: "{{ ldap_bind_pw }}"
- server_uri: "{{ ldap_server_uri }}"
- dn: "{{ item }}"
- state: absent
- with_items: "{{ groups_to_delete }}"
-
- - name: Prune groups
- community.okd.openshift_adm_groups_sync:
- config: "{{ config_simple_tolerate_not_found }}"
- state: absent
- register: result
- check_mode: yes
-
- - name: Validate that only developers group is candidate for Prune
- assert:
- that:
- - result is changed
- - result.groups | length == 1
- - result.groups.0.metadata.name == "developers"
-
- - name: Read Group (validate that check_mode did not performed update in the cluster)
- kubernetes.core.k8s_info:
- kind: Group
- version: "user.openshift.io/v1"
- name: developers
- register: result
-
- - name: Assert group was found
- assert:
- that:
- - result.resources | length == 1
-
- - name: Prune using allow_groups
- community.okd.openshift_adm_groups_sync:
- config: "{{ config_simple_tolerate_not_found }}"
- allow_groups:
+ version: "user.openshift.io/v1"
+ name: "{{ item }}"
+ with_items:
+ - admins
+ - engineers
- developers
- state: absent
- register: result
- check_mode: yes
- - name: assert developers group was candidate for prune
- assert:
- that:
- - result is changed
- - result.groups | length == 1
- - result.groups.0.metadata.name == "developers"
+ - name: Delete existing LDAP entries
+ openshift_ldap_entry:
+ bind_dn: "{{ ldap_bind_dn }}"
+ bind_pw: "{{ ldap_bind_pw }}"
+ server_uri: "{{ ldap_server_uri }}"
+ dn: "{{ item.dn }}"
+ state: absent
+ with_items: "{{ ldap_resources.users + ldap_resources.groups + ldap_resources.units | reverse | list }}"
- - name: Prune using deny_groups
- community.okd.openshift_adm_groups_sync:
- config: "{{ config_simple_tolerate_not_found }}"
- deny_groups:
- - developers
- state: absent
- register: result
- check_mode: yes
+ - name: Create LDAP units
+ openshift_ldap_entry:
+ bind_dn: "{{ ldap_bind_dn }}"
+ bind_pw: "{{ ldap_bind_pw }}"
+ server_uri: "{{ ldap_server_uri }}"
+ dn: "{{ item.dn }}"
+ attributes: "{{ item.attr }}"
+ objectClass: "{{ item.class }}"
+ with_items: "{{ ldap_resources.units }}"
- - name: assert nothing found candidate for prune
- assert:
- that:
- - result is not changed
- - result.groups | length == 0
+ - name: Create LDAP Groups
+ openshift_ldap_entry:
+ bind_dn: "{{ ldap_bind_dn }}"
+ bind_pw: "{{ ldap_bind_pw }}"
+ server_uri: "{{ ldap_server_uri }}"
+ dn: "{{ item.dn }}"
+ attributes: "{{ item.attr }}"
+ objectClass: "{{ item.class }}"
+ with_items: "{{ ldap_resources.groups }}"
- - name: Prune groups
- community.okd.openshift_adm_groups_sync:
- config: "{{ config_simple_tolerate_not_found }}"
- state: absent
- register: result
+ - name: Create LDAP users
+ openshift_ldap_entry:
+ bind_dn: "{{ ldap_bind_dn }}"
+ bind_pw: "{{ ldap_bind_pw }}"
+ server_uri: "{{ ldap_server_uri }}"
+ dn: "{{ item.dn }}"
+ attributes: "{{ item.attr }}"
+ objectClass: "{{ item.class }}"
+ with_items: "{{ ldap_resources.users }}"
- - name: Validate result is changed
- assert:
- that:
- - result is changed
- - result.groups | length == 1
+ - name: Load test configurations
+ set_fact:
+ configs: "{{ lookup('template', 'rfc2307/sync-config.j2') | from_yaml }}"
- - name: Get developers group info
- kubernetes.core.k8s_info:
- kind: Group
- version: "user.openshift.io/v1"
- name: developers
- register: result
+ - name: Synchronize Groups
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ configs.simple }}"
+ check_mode: yes
+ register: result
- - name: assert group was deleted
- assert:
- that:
- - result.resources | length == 0
+ - name: Validate Group going to be created
+ assert:
+ that:
+ - result is changed
+ - admins_group
+ - devs_group
+ - '"jane.smith@ansible.org" in {{ admins_group.users }}'
+ - '"jim.adams@ansible.org" in {{ devs_group.users }}'
+ - '"jordanbulls@ansible.org" in {{ devs_group.users }}'
+ - admins_group.users | length == 1
+ - devs_group.users | length == 2
+ vars:
+ admins_group: "{{ result.groups | selectattr('metadata.name', 'equalto', 'admins') | first }}"
+ devs_group: "{{ result.groups | selectattr('metadata.name', 'equalto', 'developers') | first }}"
- - name: Get admins group info
- kubernetes.core.k8s_info:
- kind: Group
- version: "user.openshift.io/v1"
- name: admins
- register: result
+ - name: Synchronize Groups - User defined mapping
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ configs.user_defined }}"
+ check_mode: yes
+ register: result
- - name: assert group was not deleted
- assert:
- that:
- - result.resources | length == 1
+ - name: Validate Group going to be created
+ assert:
+ that:
+ - result is changed
+ - admins_group
+ - devs_group
+ - '"jane.smith@ansible.org" in {{ admins_group.users }}'
+ - '"jim.adams@ansible.org" in {{ devs_group.users }}'
+ - '"jordanbulls@ansible.org" in {{ devs_group.users }}'
+ - admins_group.users | length == 1
+ - devs_group.users | length == 2
+ vars:
+ admins_group: "{{ result.groups | selectattr('metadata.name', 'equalto', 'ansible-admins') | first }}"
+ devs_group: "{{ result.groups | selectattr('metadata.name', 'equalto', 'ansible-devs') | first }}"
- - name: Prune groups once again (idempotency)
- community.okd.openshift_adm_groups_sync:
- config: "{{ config_simple_tolerate_not_found }}"
- state: absent
- register: result
+ - name: Synchronize Groups - Using dn for every query
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ configs.dn_everywhere }}"
+ check_mode: yes
+ register: result
- - name: Assert nothing changed
- assert:
- that:
- - result is not changed
- - result.groups | length == 0
+ - name: Validate Group going to be created
+ assert:
+ that:
+ - result is changed
+ - admins_group
+ - devs_group
+ - '"cn=Jane,ou=people,ou=rfc2307,{{ ldap_root }}" in {{ admins_group.users }}'
+ - '"cn=Jim,ou=people,ou=rfc2307,{{ ldap_root }}" in {{ devs_group.users }}'
+ - '"cn=Jordan,ou=people,ou=rfc2307,{{ ldap_root }}" in {{ devs_group.users }}'
+ - admins_group.users | length == 1
+ - devs_group.users | length == 2
+ vars:
+ admins_group: "{{ result.groups | selectattr('metadata.name', 'equalto', 'cn=admins,ou=groups,ou=rfc2307,' + ldap_root ) | first }}"
+ devs_group: "{{ result.groups | selectattr('metadata.name', 'equalto', 'cn=developers,ou=groups,ou=rfc2307,' + ldap_root ) | first }}"
+
+ - name: Synchronize Groups - Partially user defined mapping
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ configs.partially_user_defined }}"
+ check_mode: yes
+ register: result
+
+ - name: Validate Group going to be created
+ assert:
+ that:
+ - result is changed
+ - admins_group
+ - devs_group
+ - '"jane.smith@ansible.org" in {{ admins_group.users }}'
+ - '"jim.adams@ansible.org" in {{ devs_group.users }}'
+ - '"jordanbulls@ansible.org" in {{ devs_group.users }}'
+ - admins_group.users | length == 1
+ - devs_group.users | length == 2
+ vars:
+ admins_group: "{{ result.groups | selectattr('metadata.name', 'equalto', 'ansible-admins') | first }}"
+ devs_group: "{{ result.groups | selectattr('metadata.name', 'equalto', 'developers') | first }}"
+
+ - name: Delete Group 'engineers' if created before
+ community.okd.k8s:
+ state: absent
+ kind: Group
+ version: "user.openshift.io/v1"
+ name: 'engineers'
+ wait: yes
+ ignore_errors: yes
+
+ - name: Synchronize Groups - Partially user defined mapping
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ configs.out_scope }}"
+ check_mode: yes
+ register: result
+ ignore_errors: yes
+
+ - name: Assert group sync failed due to non-existent member
+ assert:
+ that:
+ - result is failed
+ - result.msg.startswith("Entry not found for base='cn=Matthew,ou=people,ou=outrfc2307,{{ ldap_root }}'")
+
+ - name: Define sync configuration with tolerateMemberNotFoundErrors
+ set_fact:
+ config_out_of_scope_tolerate_not_found: "{{ configs.out_scope | combine({'rfc2307': merge_rfc2307 })}}"
+ vars:
+ merge_rfc2307: "{{ configs.out_scope.rfc2307 | combine({'tolerateMemberNotFoundErrors': 'true'}) }}"
+
+ - name: Synchronize Groups - Partially user defined mapping (tolerateMemberNotFoundErrors=true)
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ config_out_of_scope_tolerate_not_found }}"
+ check_mode: yes
+ register: result
+
+ - name: Assert group sync did not fail (tolerateMemberNotFoundErrors=true)
+ assert:
+ that:
+ - result is changed
+ - result.groups | length == 1
+ - result.groups.0.metadata.name == 'engineers'
+ - result.groups.0.users == ['Abraham']
+
+ - name: Create Group 'engineers'
+ community.okd.k8s:
+ state: present
+ wait: yes
+ definition:
+ kind: Group
+ apiVersion: "user.openshift.io/v1"
+ metadata:
+ name: engineers
+ users: []
+
+ - name: Try to sync LDAP group with Openshift existing group not created using sync should failed
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ config_out_of_scope_tolerate_not_found }}"
+ check_mode: yes
+ register: result
+ ignore_errors: yes
+
+ - name: Validate group sync failed
+ assert:
+ that:
+ - result is failed
+ - '"openshift.io/ldap.host label did not match sync host" in result.msg'
+
+ - name: Define allow_groups and deny_groups groups
+ set_fact:
+ allow_groups:
+ - "cn=developers,ou=groups,ou=rfc2307,{{ ldap_root }}"
+ deny_groups:
+ - "cn=admins,ou=groups,ou=rfc2307,{{ ldap_root }}"
+
+ - name: Synchronize Groups using allow_groups
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ configs.simple }}"
+ allow_groups: "{{ allow_groups }}"
+ register: result
+ check_mode: yes
+
+ - name: Validate Group going to be created
+ assert:
+ that:
+ - result is changed
+ - result.groups | length == 1
+ - result.groups.0.metadata.name == "developers"
+
+ - name: Synchronize Groups using deny_groups
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ configs.simple }}"
+ deny_groups: "{{ deny_groups }}"
+ register: result
+ check_mode: yes
+
+ - name: Validate Group going to be created
+ assert:
+ that:
+ - result is changed
+ - result.groups | length == 1
+ - result.groups.0.metadata.name == "developers"
+
+ - name: Synchronize groups, remove check_mode
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ configs.simple }}"
+ register: result
+
+ - name: Validate result is changed
+ assert:
+ that:
+ - result is changed
+
+ - name: Read Groups
+ kubernetes.core.k8s_info:
+ kind: Group
+ version: "user.openshift.io/v1"
+ name: admins
+ register: result
+
+ - name: Validate group was created
+ assert:
+ that:
+ - result.resources | length == 1
+ - '"jane.smith@ansible.org" in {{ result.resources.0.users }}'
+
+ - name: Read Groups
+ kubernetes.core.k8s_info:
+ kind: Group
+ version: "user.openshift.io/v1"
+ name: developers
+ register: result
+
+ - name: Validate group was created
+ assert:
+ that:
+ - result.resources | length == 1
+ - '"jim.adams@ansible.org" in {{ result.resources.0.users }}'
+ - '"jordanbulls@ansible.org" in {{ result.resources.0.users }}'
+
+ - name: Set users to delete (no admins users anymore and only 1 developer kept)
+ set_fact:
+ users_to_delete:
+ - "cn=Jane,ou=people,ou=rfc2307,{{ ldap_root }}"
+ - "cn=Jim,ou=people,ou=rfc2307,{{ ldap_root }}"
+
+ - name: Delete users from LDAP servers
+ openshift_ldap_entry:
+ bind_dn: "{{ ldap_bind_dn }}"
+ bind_pw: "{{ ldap_bind_pw }}"
+ server_uri: "{{ ldap_server_uri }}"
+ dn: "{{ item }}"
+ state: absent
+ with_items: "{{ users_to_delete }}"
+
+ - name: Define sync configuration with tolerateMemberNotFoundErrors
+ set_fact:
+ config_simple_tolerate_not_found: "{{ configs.simple | combine({'rfc2307': merge_rfc2307 })}}"
+ vars:
+ merge_rfc2307: "{{ configs.simple.rfc2307 | combine({'tolerateMemberNotFoundErrors': 'true'}) }}"
+
+ - name: Synchronize groups once again after users deletion
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ config_simple_tolerate_not_found }}"
+ register: result
+
+ - name: Validate result is changed
+ assert:
+ that:
+ - result is changed
+
+ - name: Read Groups
+ kubernetes.core.k8s_info:
+ kind: Group
+ version: "user.openshift.io/v1"
+ name: admins
+ register: result
+
+ - name: Validate admins group does not contains users anymore
+ assert:
+ that:
+ - result.resources | length == 1
+ - result.resources.0.users == []
+
+ - name: Read Groups
+ kubernetes.core.k8s_info:
+ kind: Group
+ version: "user.openshift.io/v1"
+ name: developers
+ register: result
+
+ - name: Validate group was created
+ assert:
+ that:
+ - result.resources | length == 1
+ - '"jordanbulls@ansible.org" in {{ result.resources.0.users }}'
+
+ - name: Set group to delete
+ set_fact:
+ groups_to_delete:
+ - "cn=developers,ou=groups,ou=rfc2307,{{ ldap_root }}"
+
+ - name: Delete Group from LDAP servers
+ openshift_ldap_entry:
+ bind_dn: "{{ ldap_bind_dn }}"
+ bind_pw: "{{ ldap_bind_pw }}"
+ server_uri: "{{ ldap_server_uri }}"
+ dn: "{{ item }}"
+ state: absent
+ with_items: "{{ groups_to_delete }}"
+
+ - name: Prune groups
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ config_simple_tolerate_not_found }}"
+ state: absent
+ register: result
+ check_mode: yes
+
+ - name: Validate that only developers group is candidate for Prune
+ assert:
+ that:
+ - result is changed
+ - result.groups | length == 1
+ - result.groups.0.metadata.name == "developers"
+
+ - name: Read Group (validate that check_mode did not performed update in the cluster)
+ kubernetes.core.k8s_info:
+ kind: Group
+ version: "user.openshift.io/v1"
+ name: developers
+ register: result
+
+ - name: Assert group was found
+ assert:
+ that:
+ - result.resources | length == 1
+
+ - name: Prune using allow_groups
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ config_simple_tolerate_not_found }}"
+ allow_groups:
+ - developers
+ state: absent
+ register: result
+ check_mode: yes
+
+ - name: assert developers group was candidate for prune
+ assert:
+ that:
+ - result is changed
+ - result.groups | length == 1
+ - result.groups.0.metadata.name == "developers"
+
+ - name: Prune using deny_groups
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ config_simple_tolerate_not_found }}"
+ deny_groups:
+ - developers
+ state: absent
+ register: result
+ check_mode: yes
+
+ - name: assert nothing found candidate for prune
+ assert:
+ that:
+ - result is not changed
+ - result.groups | length == 0
+
+ - name: Prune groups
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ config_simple_tolerate_not_found }}"
+ state: absent
+ register: result
+
+ - name: Validate result is changed
+ assert:
+ that:
+ - result is changed
+ - result.groups | length == 1
+
+ - name: Get developers group info
+ kubernetes.core.k8s_info:
+ kind: Group
+ version: "user.openshift.io/v1"
+ name: developers
+ register: result
+
+ - name: assert group was deleted
+ assert:
+ that:
+ - result.resources | length == 0
+
+ - name: Get admins group info
+ kubernetes.core.k8s_info:
+ kind: Group
+ version: "user.openshift.io/v1"
+ name: admins
+ register: result
+
+ - name: assert group was not deleted
+ assert:
+ that:
+ - result.resources | length == 1
+
+ - name: Prune groups once again (idempotency)
+ community.okd.openshift_adm_groups_sync:
+ config: "{{ config_simple_tolerate_not_found }}"
+ state: absent
+ register: result
+
+ - name: Assert nothing changed
+ assert:
+ that:
+ - result is not changed
+ - result.groups | length == 0
always:
- name: Delete openshift groups if existing
diff --git a/molecule/default/tasks/openshift_adm_prune_auth_clusterroles.yml b/molecule/default/tasks/openshift_adm_prune_auth_clusterroles.yml
index 4de4894..edf0e17 100644
--- a/molecule/default/tasks/openshift_adm_prune_auth_clusterroles.yml
+++ b/molecule/default/tasks/openshift_adm_prune_auth_clusterroles.yml
@@ -1,293 +1,294 @@
+---
- block:
- - set_fact:
- test_sa: "clusterrole-sa"
- test_ns: "clusterrole-ns"
+ - set_fact:
+ test_sa: "clusterrole-sa"
+ test_ns: "clusterrole-ns"
- - name: Ensure namespace
- kubernetes.core.k8s:
- kind: Namespace
- name: "{{ test_ns }}"
+ - name: Ensure namespace
+ kubernetes.core.k8s:
+ kind: Namespace
+ name: "{{ test_ns }}"
- - name: Get cluster information
- kubernetes.core.k8s_cluster_info:
- register: cluster_info
- no_log: true
+ - name: Get cluster information
+ kubernetes.core.k8s_cluster_info:
+ register: cluster_info
+ no_log: true
- - set_fact:
- cluster_host: "{{ cluster_info['connection']['host'] }}"
+ - set_fact:
+ cluster_host: "{{ cluster_info['connection']['host'] }}"
- - name: Create Service account
- kubernetes.core.k8s:
- definition:
- apiVersion: v1
+ - name: Create Service account
+ kubernetes.core.k8s:
+ definition:
+ apiVersion: v1
+ kind: ServiceAccount
+ metadata:
+ name: "{{ test_sa }}"
+ namespace: "{{ test_ns }}"
+
+ - name: Read Service Account
+ kubernetes.core.k8s_info:
kind: ServiceAccount
- metadata:
- name: "{{ test_sa }}"
- namespace: "{{ test_ns }}"
+ namespace: "{{ test_ns }}"
+ name: "{{ test_sa }}"
+ register: result
- - name: Read Service Account
- kubernetes.core.k8s_info:
- kind: ServiceAccount
- namespace: "{{ test_ns }}"
- name: "{{ test_sa }}"
- register: result
+ - set_fact:
+ secret_token: "{{ result.resources[0]['secrets'][0]['name'] }}"
- - set_fact:
- secret_token: "{{ result.resources[0]['secrets'][0]['name'] }}"
+ - name: Get secret details
+ kubernetes.core.k8s_info:
+ kind: Secret
+ namespace: '{{ test_ns }}'
+ name: '{{ secret_token }}'
+ register: _secret
+ retries: 10
+ delay: 10
+ until:
+ - ("'openshift.io/token-secret.value' in _secret.resources[0]['metadata']['annotations']") or ("'token' in _secret.resources[0]['data']")
- - name: Get secret details
- kubernetes.core.k8s_info:
- kind: Secret
- namespace: '{{ test_ns }}'
- name: '{{ secret_token }}'
- register: _secret
- retries: 10
- delay: 10
- until:
- - ("'openshift.io/token-secret.value' in _secret.resources[0]['metadata']['annotations']") or ("'token' in _secret.resources[0]['data']")
+ - set_fact:
+ api_token: "{{ _secret.resources[0]['metadata']['annotations']['openshift.io/token-secret.value'] }}"
+ when: "'openshift.io/token-secret.value' in _secret.resources[0]['metadata']['annotations']"
- - set_fact:
- api_token: "{{ _secret.resources[0]['metadata']['annotations']['openshift.io/token-secret.value'] }}"
- when: "'openshift.io/token-secret.value' in _secret.resources[0]['metadata']['annotations']"
+ - set_fact:
+ api_token: "{{ _secret.resources[0]['data']['token'] | b64decode }}"
+ when: "'token' in _secret.resources[0]['data']"
- - set_fact:
- api_token: "{{ _secret.resources[0]['data']['token'] | b64decode }}"
- when: "'token' in _secret.resources[0]['data']"
+ - name: list Node should failed (forbidden user)
+ kubernetes.core.k8s_info:
+ api_key: "{{ api_token }}"
+ host: "{{ cluster_host }}"
+ validate_certs: no
+ kind: Node
+ register: error
+ ignore_errors: true
- - name: list Node should failed (forbidden user)
- kubernetes.core.k8s_info:
- api_key: "{{ api_token }}"
- host: "{{ cluster_host }}"
- validate_certs: no
- kind: Node
- register: error
- ignore_errors: true
+ - assert:
+ that:
+ - '"nodes is forbidden: User" in error.msg'
- - assert:
- that:
- - '"nodes is forbidden: User" in error.msg'
+ - name: list Pod for all namespace should failed
+ kubernetes.core.k8s_info:
+ api_key: "{{ api_token }}"
+ host: "{{ cluster_host }}"
+ validate_certs: no
+ kind: Pod
+ register: error
+ ignore_errors: true
- - name: list Pod for all namespace should failed
- kubernetes.core.k8s_info:
- api_key: "{{ api_token }}"
- host: "{{ cluster_host }}"
- validate_certs: no
- kind: Pod
- register: error
- ignore_errors: true
+ - assert:
+ that:
+ - '"pods is forbidden: User" in error.msg'
- - assert:
- that:
- - '"pods is forbidden: User" in error.msg'
+ - name: list Pod for test namespace should failed
+ kubernetes.core.k8s_info:
+ api_key: "{{ api_token }}"
+ host: "{{ cluster_host }}"
+ validate_certs: no
+ kind: Pod
+ namespace: "{{ test_ns }}"
+ register: error
+ ignore_errors: true
- - name: list Pod for test namespace should failed
- kubernetes.core.k8s_info:
- api_key: "{{ api_token }}"
- host: "{{ cluster_host }}"
- validate_certs: no
- kind: Pod
- namespace: "{{ test_ns }}"
- register: error
- ignore_errors: true
+ - assert:
+ that:
+ - '"pods is forbidden: User" in error.msg'
- - assert:
- that:
- - '"pods is forbidden: User" in error.msg'
+ - set_fact:
+ test_labels:
+ phase: dev
+ cluster_roles:
+ - name: pod-manager
+ resources:
+ - pods
+ verbs:
+ - list
+ api_version_binding: "authorization.openshift.io/v1"
+ - name: node-manager
+ resources:
+ - nodes
+ verbs:
+ - list
+ api_version_binding: "rbac.authorization.k8s.io/v1"
- - set_fact:
- test_labels:
- phase: dev
- cluster_roles:
- - name: pod-manager
- resources:
- - pods
- verbs:
- - list
- api_version_binding: "authorization.openshift.io/v1"
- - name: node-manager
- resources:
- - nodes
- verbs:
- - list
- api_version_binding: "rbac.authorization.k8s.io/v1"
-
- - name: Create cluster roles
- kubernetes.core.k8s:
- definition:
- kind: ClusterRole
- apiVersion: "rbac.authorization.k8s.io/v1"
- metadata:
- name: "{{ item.name }}"
- labels: "{{ test_labels }}"
- rules:
- - apiGroups: [""]
- resources: "{{ item.resources }}"
- verbs: "{{ item.verbs }}"
- with_items: '{{ cluster_roles }}'
-
- - name: Create Role Binding (namespaced)
- kubernetes.core.k8s:
- definition:
- kind: RoleBinding
- apiVersion: "rbac.authorization.k8s.io/v1"
- metadata:
- name: "{{ cluster_roles[0].name }}-binding"
- namespace: "{{ test_ns }}"
- labels: "{{ test_labels }}"
- subjects:
- - kind: ServiceAccount
- name: "{{ test_sa }}"
- namespace: "{{ test_ns }}"
- apiGroup: ""
- roleRef:
+ - name: Create cluster roles
+ kubernetes.core.k8s:
+ definition:
kind: ClusterRole
- name: "{{ cluster_roles[0].name }}"
- apiGroup: ""
+ apiVersion: "rbac.authorization.k8s.io/v1"
+ metadata:
+ name: "{{ item.name }}"
+ labels: "{{ test_labels }}"
+ rules:
+ - apiGroups: [""]
+ resources: "{{ item.resources }}"
+ verbs: "{{ item.verbs }}"
+ with_items: '{{ cluster_roles }}'
- - name: list Pod for all namespace should failed
- kubernetes.core.k8s_info:
- api_key: "{{ api_token }}"
- host: "{{ cluster_host }}"
- validate_certs: no
- kind: Pod
- register: error
- ignore_errors: true
+ - name: Create Role Binding (namespaced)
+ kubernetes.core.k8s:
+ definition:
+ kind: RoleBinding
+ apiVersion: "rbac.authorization.k8s.io/v1"
+ metadata:
+ name: "{{ cluster_roles[0].name }}-binding"
+ namespace: "{{ test_ns }}"
+ labels: "{{ test_labels }}"
+ subjects:
+ - kind: ServiceAccount
+ name: "{{ test_sa }}"
+ namespace: "{{ test_ns }}"
+ apiGroup: ""
+ roleRef:
+ kind: ClusterRole
+ name: "{{ cluster_roles[0].name }}"
+ apiGroup: ""
- - assert:
- that:
- - '"pods is forbidden: User" in error.msg'
+ - name: list Pod for all namespace should failed
+ kubernetes.core.k8s_info:
+ api_key: "{{ api_token }}"
+ host: "{{ cluster_host }}"
+ validate_certs: no
+ kind: Pod
+ register: error
+ ignore_errors: true
- - name: list Pod for test namespace should succeed
- kubernetes.core.k8s_info:
- api_key: "{{ api_token }}"
- host: "{{ cluster_host }}"
- validate_certs: no
- kind: Pod
- namespace: "{{ test_ns }}"
- no_log: true
+ - assert:
+ that:
+ - '"pods is forbidden: User" in error.msg'
- - name: Create Cluster role Binding
- kubernetes.core.k8s:
- definition:
- kind: ClusterRoleBinding
- apiVersion: "{{ item.api_version_binding }}"
- metadata:
- name: "{{ item.name }}-binding"
- labels: "{{ test_labels }}"
- subjects:
- - kind: ServiceAccount
- name: "{{ test_sa }}"
- namespace: "{{ test_ns }}"
- apiGroup: ""
- roleRef:
- kind: ClusterRole
- name: "{{ item.name }}"
- apiGroup: ""
- with_items: "{{ cluster_roles }}"
+ - name: list Pod for test namespace should succeed
+ kubernetes.core.k8s_info:
+ api_key: "{{ api_token }}"
+ host: "{{ cluster_host }}"
+ validate_certs: no
+ kind: Pod
+ namespace: "{{ test_ns }}"
+ no_log: true
- - name: list Pod for all namespace should succeed
- kubernetes.core.k8s_info:
- api_key: "{{ api_token }}"
- host: "{{ cluster_host }}"
- validate_certs: no
- kind: Pod
- no_log: true
+ - name: Create Cluster role Binding
+ kubernetes.core.k8s:
+ definition:
+ kind: ClusterRoleBinding
+ apiVersion: "{{ item.api_version_binding }}"
+ metadata:
+ name: "{{ item.name }}-binding"
+ labels: "{{ test_labels }}"
+ subjects:
+ - kind: ServiceAccount
+ name: "{{ test_sa }}"
+ namespace: "{{ test_ns }}"
+ apiGroup: ""
+ roleRef:
+ kind: ClusterRole
+ name: "{{ item.name }}"
+ apiGroup: ""
+ with_items: "{{ cluster_roles }}"
- - name: list Pod for test namespace should succeed
- kubernetes.core.k8s_info:
- api_key: "{{ api_token }}"
- host: "{{ cluster_host }}"
- validate_certs: no
- kind: Pod
- namespace: "{{ test_ns }}"
- no_log: true
+ - name: list Pod for all namespace should succeed
+ kubernetes.core.k8s_info:
+ api_key: "{{ api_token }}"
+ host: "{{ cluster_host }}"
+ validate_certs: no
+ kind: Pod
+ no_log: true
- - name: list Node using ServiceAccount
- kubernetes.core.k8s_info:
- api_key: "{{ api_token }}"
- host: "{{ cluster_host }}"
- validate_certs: no
- kind: Node
- namespace: "{{ test_ns }}"
- no_log: true
+ - name: list Pod for test namespace should succeed
+ kubernetes.core.k8s_info:
+ api_key: "{{ api_token }}"
+ host: "{{ cluster_host }}"
+ validate_certs: no
+ kind: Pod
+ namespace: "{{ test_ns }}"
+ no_log: true
- - name: Prune clusterroles (check mode)
- community.okd.openshift_adm_prune_auth:
- resource: clusterroles
- label_selectors:
- - phase=dev
- register: check
- check_mode: true
+ - name: list Node using ServiceAccount
+ kubernetes.core.k8s_info:
+ api_key: "{{ api_token }}"
+ host: "{{ cluster_host }}"
+ validate_certs: no
+ kind: Node
+ namespace: "{{ test_ns }}"
+ no_log: true
- - name: validate clusterrole binding candidates for prune
- assert:
- that:
- - '"{{ item.name }}-binding" in check.cluster_role_binding'
- - '"{{ test_ns }}/{{ cluster_roles[0].name }}-binding" in check.role_binding'
- with_items: "{{ cluster_roles }}"
+ - name: Prune clusterroles (check mode)
+ community.okd.openshift_adm_prune_auth:
+ resource: clusterroles
+ label_selectors:
+ - phase=dev
+ register: check
+ check_mode: true
- - name: Prune Cluster Role for managing Pod
- community.okd.openshift_adm_prune_auth:
- resource: clusterroles
- name: "{{ cluster_roles[0].name }}"
+ - name: validate clusterrole binding candidates for prune
+ assert:
+ that:
+ - '"{{ item.name }}-binding" in check.cluster_role_binding'
+ - '"{{ test_ns }}/{{ cluster_roles[0].name }}-binding" in check.role_binding'
+ with_items: "{{ cluster_roles }}"
- - name: list Pod for all namespace should failed
- kubernetes.core.k8s_info:
- api_key: "{{ api_token }}"
- host: "{{ cluster_host }}"
- validate_certs: no
- kind: Pod
- register: error
- no_log: true
- ignore_errors: true
+ - name: Prune Cluster Role for managing Pod
+ community.okd.openshift_adm_prune_auth:
+ resource: clusterroles
+ name: "{{ cluster_roles[0].name }}"
- - assert:
- that:
- - '"pods is forbidden: User" in error.msg'
+ - name: list Pod for all namespace should failed
+ kubernetes.core.k8s_info:
+ api_key: "{{ api_token }}"
+ host: "{{ cluster_host }}"
+ validate_certs: no
+ kind: Pod
+ register: error
+ no_log: true
+ ignore_errors: true
- - name: list Pod for test namespace should failed
- kubernetes.core.k8s_info:
- api_key: "{{ api_token }}"
- host: "{{ cluster_host }}"
- validate_certs: no
- kind: Pod
- namespace: "{{ test_ns }}"
- register: error
- no_log: true
- ignore_errors: true
+ - assert:
+ that:
+ - '"pods is forbidden: User" in error.msg'
- - assert:
- that:
- - '"pods is forbidden: User" in error.msg'
+ - name: list Pod for test namespace should failed
+ kubernetes.core.k8s_info:
+ api_key: "{{ api_token }}"
+ host: "{{ cluster_host }}"
+ validate_certs: no
+ kind: Pod
+ namespace: "{{ test_ns }}"
+ register: error
+ no_log: true
+ ignore_errors: true
- - name: list Node using ServiceAccount
- kubernetes.core.k8s_info:
- api_key: "{{ api_token }}"
- host: "{{ cluster_host }}"
- validate_certs: no
- kind: Node
- namespace: "{{ test_ns }}"
- no_log: true
+ - assert:
+ that:
+ - '"pods is forbidden: User" in error.msg'
- - name: Prune clusterroles (remaining)
- community.okd.openshift_adm_prune_auth:
- resource: clusterroles
- label_selectors:
- - phase=dev
+ - name: list Node using ServiceAccount
+ kubernetes.core.k8s_info:
+ api_key: "{{ api_token }}"
+ host: "{{ cluster_host }}"
+ validate_certs: no
+ kind: Node
+ namespace: "{{ test_ns }}"
+ no_log: true
- - name: list Node using ServiceAccount should fail
- kubernetes.core.k8s_info:
- api_key: "{{ api_token }}"
- host: "{{ cluster_host }}"
- validate_certs: no
- kind: Node
- namespace: "{{ test_ns }}"
- register: error
- ignore_errors: true
+ - name: Prune clusterroles (remaining)
+ community.okd.openshift_adm_prune_auth:
+ resource: clusterroles
+ label_selectors:
+ - phase=dev
- - assert:
- that:
- - '"nodes is forbidden: User" in error.msg'
+ - name: list Node using ServiceAccount should fail
+ kubernetes.core.k8s_info:
+ api_key: "{{ api_token }}"
+ host: "{{ cluster_host }}"
+ validate_certs: no
+ kind: Node
+ namespace: "{{ test_ns }}"
+ register: error
+ ignore_errors: true
+
+ - assert:
+ that:
+ - '"nodes is forbidden: User" in error.msg'
always:
- name: Ensure namespace is deleted
diff --git a/molecule/default/tasks/openshift_adm_prune_auth_roles.yml b/molecule/default/tasks/openshift_adm_prune_auth_roles.yml
index 1724a19..7b75a0c 100644
--- a/molecule/default/tasks/openshift_adm_prune_auth_roles.yml
+++ b/molecule/default/tasks/openshift_adm_prune_auth_roles.yml
@@ -1,335 +1,336 @@
+---
- block:
- - set_fact:
- test_ns: "prune-roles"
- sa_name: "roles-sa"
- pod_name: "pod-prune"
- role_definition:
- - name: pod-list
- labels:
- action: list
- verbs:
- - list
- role_binding:
- api_version: rbac.authorization.k8s.io/v1
- - name: pod-create
- labels:
- action: create
- verbs:
- - create
- - get
- role_binding:
- api_version: authorization.openshift.io/v1
- - name: pod-delete
- labels:
- action: delete
- verbs:
- - delete
- role_binding:
- api_version: rbac.authorization.k8s.io/v1
+ - set_fact:
+ test_ns: "prune-roles"
+ sa_name: "roles-sa"
+ pod_name: "pod-prune"
+ role_definition:
+ - name: pod-list
+ labels:
+ action: list
+ verbs:
+ - list
+ role_binding:
+ api_version: rbac.authorization.k8s.io/v1
+ - name: pod-create
+ labels:
+ action: create
+ verbs:
+ - create
+ - get
+ role_binding:
+ api_version: authorization.openshift.io/v1
+ - name: pod-delete
+ labels:
+ action: delete
+ verbs:
+ - delete
+ role_binding:
+ api_version: rbac.authorization.k8s.io/v1
- - name: Ensure namespace
- kubernetes.core.k8s:
- kind: Namespace
- name: '{{ test_ns }}'
+ - name: Ensure namespace
+ kubernetes.core.k8s:
+ kind: Namespace
+ name: '{{ test_ns }}'
- - name: Get cluster information
- kubernetes.core.k8s_cluster_info:
- register: cluster_info
- no_log: true
+ - name: Get cluster information
+ kubernetes.core.k8s_cluster_info:
+ register: cluster_info
+ no_log: true
- - set_fact:
- cluster_host: "{{ cluster_info['connection']['host'] }}"
+ - set_fact:
+ cluster_host: "{{ cluster_info['connection']['host'] }}"
- - name: Create Service account
- kubernetes.core.k8s:
- definition:
- apiVersion: v1
+ - name: Create Service account
+ kubernetes.core.k8s:
+ definition:
+ apiVersion: v1
+ kind: ServiceAccount
+ metadata:
+ name: '{{ sa_name }}'
+ namespace: '{{ test_ns }}'
+
+ - name: Read Service Account
+ kubernetes.core.k8s_info:
kind: ServiceAccount
- metadata:
- name: '{{ sa_name }}'
- namespace: '{{ test_ns }}'
+ namespace: '{{ test_ns }}'
+ name: '{{ sa_name }}'
+ register: sa_out
- - name: Read Service Account
- kubernetes.core.k8s_info:
- kind: ServiceAccount
- namespace: '{{ test_ns }}'
- name: '{{ sa_name }}'
- register: sa_out
+ - set_fact:
+ secret_token: "{{ sa_out.resources[0]['secrets'][0]['name'] }}"
- - set_fact:
- secret_token: "{{ sa_out.resources[0]['secrets'][0]['name'] }}"
+ - name: Get secret details
+ kubernetes.core.k8s_info:
+ kind: Secret
+ namespace: '{{ test_ns }}'
+ name: '{{ secret_token }}'
+ register: r_secret
+ retries: 10
+ delay: 10
+ until:
+ - ("'openshift.io/token-secret.value' in r_secret.resources[0]['metadata']['annotations']") or ("'token' in r_secret.resources[0]['data']")
- - name: Get secret details
- kubernetes.core.k8s_info:
- kind: Secret
- namespace: '{{ test_ns }}'
- name: '{{ secret_token }}'
- register: r_secret
- retries: 10
- delay: 10
- until:
- - ("'openshift.io/token-secret.value' in r_secret.resources[0]['metadata']['annotations']") or ("'token' in r_secret.resources[0]['data']")
+ - set_fact:
+ api_token: "{{ r_secret.resources[0]['metadata']['annotations']['openshift.io/token-secret.value'] }}"
+ when: "'openshift.io/token-secret.value' in r_secret.resources[0]['metadata']['annotations']"
- - set_fact:
- api_token: "{{ r_secret.resources[0]['metadata']['annotations']['openshift.io/token-secret.value'] }}"
- when: "'openshift.io/token-secret.value' in r_secret.resources[0]['metadata']['annotations']"
-
- - set_fact:
- api_token: "{{ r_secret.resources[0]['data']['token'] | b64decode }}"
- when: "'token' in r_secret.resources[0]['data']"
+ - set_fact:
+ api_token: "{{ r_secret.resources[0]['data']['token'] | b64decode }}"
+ when: "'token' in r_secret.resources[0]['data']"
- - name: list resources using service account
- kubernetes.core.k8s_info:
- api_key: '{{ api_token }}'
- host: '{{ cluster_host }}'
- validate_certs: no
- kind: Pod
- namespace: '{{ test_ns }}'
- register: error
- ignore_errors: true
-
- - assert:
- that:
- - '"pods is forbidden: User" in error.msg'
+ - name: list resources using service account
+ kubernetes.core.k8s_info:
+ api_key: '{{ api_token }}'
+ host: '{{ cluster_host }}'
+ validate_certs: no
+ kind: Pod
+ namespace: '{{ test_ns }}'
+ register: error
+ ignore_errors: true
- - name: Create a role to manage Pod from namespace "{{ test_ns }}"
- kubernetes.core.k8s:
- definition:
- kind: Role
- apiVersion: rbac.authorization.k8s.io/v1
- metadata:
- namespace: "{{ test_ns }}"
- name: "{{ item.name }}"
- labels: "{{ item.labels }}"
- rules:
- - apiGroups: [""]
- resources: ["pods"]
- verbs: "{{ item.verbs }}"
- with_items: "{{ role_definition }}"
+ - assert:
+ that:
+ - '"pods is forbidden: User" in error.msg'
- - name: Create Role Binding
- kubernetes.core.k8s:
- definition:
- kind: RoleBinding
- apiVersion: "{{ item.role_binding.api_version }}"
- metadata:
- name: "{{ item.name }}-bind"
- namespace: "{{ test_ns }}"
- subjects:
- - kind: ServiceAccount
- name: "{{ sa_name }}"
- namespace: "{{ test_ns }}"
- apiGroup: ""
- roleRef:
+ - name: Create a role to manage Pod from namespace "{{ test_ns }}"
+ kubernetes.core.k8s:
+ definition:
kind: Role
- name: "{{ item.name }}"
- namespace: "{{ test_ns }}"
- apiGroup: ""
- with_items: "{{ role_definition }}"
+ apiVersion: rbac.authorization.k8s.io/v1
+ metadata:
+ namespace: "{{ test_ns }}"
+ name: "{{ item.name }}"
+ labels: "{{ item.labels }}"
+ rules:
+ - apiGroups: [""]
+ resources: ["pods"]
+ verbs: "{{ item.verbs }}"
+ with_items: "{{ role_definition }}"
- - name: Create Pod should succeed
- kubernetes.core.k8s:
- api_key: "{{ api_token }}"
- host: "{{ cluster_host }}"
- validate_certs: no
- namespace: "{{ test_ns }}"
- definition:
+ - name: Create Role Binding
+ kubernetes.core.k8s:
+ definition:
+ kind: RoleBinding
+ apiVersion: "{{ item.role_binding.api_version }}"
+ metadata:
+ name: "{{ item.name }}-bind"
+ namespace: "{{ test_ns }}"
+ subjects:
+ - kind: ServiceAccount
+ name: "{{ sa_name }}"
+ namespace: "{{ test_ns }}"
+ apiGroup: ""
+ roleRef:
+ kind: Role
+ name: "{{ item.name }}"
+ namespace: "{{ test_ns }}"
+ apiGroup: ""
+ with_items: "{{ role_definition }}"
+
+ - name: Create Pod should succeed
+ kubernetes.core.k8s:
+ api_key: "{{ api_token }}"
+ host: "{{ cluster_host }}"
+ validate_certs: no
+ namespace: "{{ test_ns }}"
+ definition:
+ kind: Pod
+ metadata:
+ name: "{{ pod_name }}"
+ spec:
+ containers:
+ - name: python
+ image: python:3.7-alpine
+ command:
+ - /bin/sh
+ - -c
+ - while true; do echo $(date); sleep 15; done
+ imagePullPolicy: IfNotPresent
+ register: result
+
+ - name: assert pod creation succeed
+ assert:
+ that:
+ - result is successful
+
+ - name: List Pod
+ kubernetes.core.k8s_info:
+ api_key: "{{ api_token }}"
+ host: "{{ cluster_host }}"
+ validate_certs: no
+ namespace: "{{ test_ns }}"
kind: Pod
- metadata:
- name: "{{ pod_name }}"
- spec:
- containers:
- - name: python
- image: python:3.7-alpine
- command:
- - /bin/sh
- - -c
- - while true; do echo $(date); sleep 15; done
- imagePullPolicy: IfNotPresent
- register: result
+ register: result
- - name: assert pod creation succeed
- assert:
- that:
- - result is successful
+ - name: assert user is still authorize to list pods
+ assert:
+ that:
+ - result is successful
- - name: List Pod
- kubernetes.core.k8s_info:
- api_key: "{{ api_token }}"
- host: "{{ cluster_host }}"
- validate_certs: no
- namespace: "{{ test_ns }}"
- kind: Pod
- register: result
+ - name: Prune auth roles (check mode)
+ community.okd.openshift_adm_prune_auth:
+ resource: roles
+ namespace: "{{ test_ns }}"
+ register: check
+ check_mode: true
- - name: assert user is still authorize to list pods
- assert:
- that:
- - result is successful
+ - name: validate that list role binding are candidates for prune
+ assert:
+ that: '"{{ test_ns }}/{{ item.name }}-bind" in check.role_binding'
+ with_items: "{{ role_definition }}"
- - name: Prune auth roles (check mode)
- community.okd.openshift_adm_prune_auth:
- resource: roles
- namespace: "{{ test_ns }}"
- register: check
- check_mode: true
+ - name: Prune resource using label_selectors option
+ community.okd.openshift_adm_prune_auth:
+ resource: roles
+ namespace: "{{ test_ns }}"
+ label_selectors:
+ - action=delete
+ register: prune
- - name: validate that list role binding are candidates for prune
- assert:
- that: '"{{ test_ns }}/{{ item.name }}-bind" in check.role_binding'
- with_items: "{{ role_definition }}"
+ - name: assert that role binding 'delete' was pruned
+ assert:
+ that:
+ - prune is changed
+ - '"{{ test_ns }}/{{ role_definition[2].name }}-bind" in check.role_binding'
- - name: Prune resource using label_selectors option
- community.okd.openshift_adm_prune_auth:
- resource: roles
- namespace: "{{ test_ns }}"
- label_selectors:
- - action=delete
- register: prune
-
- - name: assert that role binding 'delete' was pruned
- assert:
- that:
- - prune is changed
- - '"{{ test_ns }}/{{ role_definition[2].name }}-bind" in check.role_binding'
-
- - name: assert that user could not delete pod anymore
- kubernetes.core.k8s:
- api_key: "{{ api_token }}"
- host: "{{ cluster_host }}"
- validate_certs: no
- state: absent
- namespace: "{{ test_ns }}"
- kind: Pod
- name: "{{ pod_name }}"
- register: result
- ignore_errors: true
-
- - name: assert pod deletion failed due to forbidden user
- assert:
- that:
- - '"forbidden: User" in error.msg'
-
- - name: List Pod
- kubernetes.core.k8s_info:
- api_key: "{{ api_token }}"
- host: "{{ cluster_host }}"
- validate_certs: no
- namespace: "{{ test_ns }}"
- kind: Pod
- register: result
-
- - name: assert user is still able to list pods
- assert:
- that:
- - result is successful
-
- - name: Create Pod should succeed
- kubernetes.core.k8s:
- api_key: "{{ api_token }}"
- host: "{{ cluster_host }}"
- validate_certs: no
- namespace: "{{ test_ns }}"
- definition:
+ - name: assert that user could not delete pod anymore
+ kubernetes.core.k8s:
+ api_key: "{{ api_token }}"
+ host: "{{ cluster_host }}"
+ validate_certs: no
+ state: absent
+ namespace: "{{ test_ns }}"
kind: Pod
- metadata:
- name: "{{ pod_name }}-1"
- spec:
- containers:
- - name: python
- image: python:3.7-alpine
- command:
- - /bin/sh
- - -c
- - while true; do echo $(date); sleep 15; done
- imagePullPolicy: IfNotPresent
- register: result
+ name: "{{ pod_name }}"
+ register: result
+ ignore_errors: true
- - name: assert user is still authorize to create pod
- assert:
- that:
- - result is successful
+ - name: assert pod deletion failed due to forbidden user
+ assert:
+ that:
+ - '"forbidden: User" in error.msg'
- - name: Prune role using name
- community.okd.openshift_adm_prune_auth:
- resource: roles
- namespace: "{{ test_ns }}"
- name: "{{ role_definition[1].name }}"
- register: prune
-
- - name: assert that role binding 'create' was pruned
- assert:
- that:
- - prune is changed
- - '"{{ test_ns }}/{{ role_definition[1].name }}-bind" in check.role_binding'
-
- - name: Create Pod (should failed)
- kubernetes.core.k8s:
- api_key: "{{ api_token }}"
- host: "{{ cluster_host }}"
- validate_certs: no
- namespace: "{{ test_ns }}"
- definition:
+ - name: List Pod
+ kubernetes.core.k8s_info:
+ api_key: "{{ api_token }}"
+ host: "{{ cluster_host }}"
+ validate_certs: no
+ namespace: "{{ test_ns }}"
kind: Pod
- metadata:
- name: "{{ pod_name }}-2"
- spec:
- containers:
- - name: python
- image: python:3.7-alpine
- command:
- - /bin/sh
- - -c
- - while true; do echo $(date); sleep 15; done
- imagePullPolicy: IfNotPresent
- register: result
- ignore_errors: true
+ register: result
- - name: assert user is not authorize to create pod anymore
- assert:
- that:
- - '"forbidden: User" in error.msg'
+ - name: assert user is still able to list pods
+ assert:
+ that:
+ - result is successful
- - name: List Pod
- kubernetes.core.k8s_info:
- api_key: "{{ api_token }}"
- host: "{{ cluster_host }}"
- validate_certs: no
- namespace: "{{ test_ns }}"
- kind: Pod
- register: result
+ - name: Create Pod should succeed
+ kubernetes.core.k8s:
+ api_key: "{{ api_token }}"
+ host: "{{ cluster_host }}"
+ validate_certs: no
+ namespace: "{{ test_ns }}"
+ definition:
+ kind: Pod
+ metadata:
+ name: "{{ pod_name }}-1"
+ spec:
+ containers:
+ - name: python
+ image: python:3.7-alpine
+ command:
+ - /bin/sh
+ - -c
+ - while true; do echo $(date); sleep 15; done
+ imagePullPolicy: IfNotPresent
+ register: result
- - name: assert user is still able to list pods
- assert:
- that:
- - result is successful
+ - name: assert user is still authorize to create pod
+ assert:
+ that:
+ - result is successful
- - name: Prune all role for namespace (neither name nor label_selectors are specified)
- community.okd.openshift_adm_prune_auth:
- resource: roles
- namespace: "{{ test_ns }}"
- register: prune
+ - name: Prune role using name
+ community.okd.openshift_adm_prune_auth:
+ resource: roles
+ namespace: "{{ test_ns }}"
+ name: "{{ role_definition[1].name }}"
+ register: prune
- - name: assert that role binding 'list' was pruned
- assert:
- that:
- - prune is changed
- - '"{{ test_ns }}/{{ role_definition[0].name }}-bind" in check.role_binding'
+ - name: assert that role binding 'create' was pruned
+ assert:
+ that:
+ - prune is changed
+ - '"{{ test_ns }}/{{ role_definition[1].name }}-bind" in check.role_binding'
- - name: List Pod
- kubernetes.core.k8s_info:
- api_key: "{{ api_token }}"
- host: "{{ cluster_host }}"
- validate_certs: no
- namespace: "{{ test_ns }}"
- kind: Pod
- register: result
- ignore_errors: true
+ - name: Create Pod (should failed)
+ kubernetes.core.k8s:
+ api_key: "{{ api_token }}"
+ host: "{{ cluster_host }}"
+ validate_certs: no
+ namespace: "{{ test_ns }}"
+ definition:
+ kind: Pod
+ metadata:
+ name: "{{ pod_name }}-2"
+ spec:
+ containers:
+ - name: python
+ image: python:3.7-alpine
+ command:
+ - /bin/sh
+ - -c
+ - while true; do echo $(date); sleep 15; done
+ imagePullPolicy: IfNotPresent
+ register: result
+ ignore_errors: true
- - name: assert user is not authorize to list pod anymore
- assert:
- that:
- - '"forbidden: User" in error.msg'
+ - name: assert user is not authorize to create pod anymore
+ assert:
+ that:
+ - '"forbidden: User" in error.msg'
+
+ - name: List Pod
+ kubernetes.core.k8s_info:
+ api_key: "{{ api_token }}"
+ host: "{{ cluster_host }}"
+ validate_certs: no
+ namespace: "{{ test_ns }}"
+ kind: Pod
+ register: result
+
+ - name: assert user is still able to list pods
+ assert:
+ that:
+ - result is successful
+
+ - name: Prune all role for namespace (neither name nor label_selectors are specified)
+ community.okd.openshift_adm_prune_auth:
+ resource: roles
+ namespace: "{{ test_ns }}"
+ register: prune
+
+ - name: assert that role binding 'list' was pruned
+ assert:
+ that:
+ - prune is changed
+ - '"{{ test_ns }}/{{ role_definition[0].name }}-bind" in check.role_binding'
+
+ - name: List Pod
+ kubernetes.core.k8s_info:
+ api_key: "{{ api_token }}"
+ host: "{{ cluster_host }}"
+ validate_certs: no
+ namespace: "{{ test_ns }}"
+ kind: Pod
+ register: result
+ ignore_errors: true
+
+ - name: assert user is not authorize to list pod anymore
+ assert:
+ that:
+ - '"forbidden: User" in error.msg'
always:
- name: Ensure namespace is deleted
diff --git a/molecule/default/tasks/openshift_adm_prune_deployments.yml b/molecule/default/tasks/openshift_adm_prune_deployments.yml
index baa0241..ca48f73 100644
--- a/molecule/default/tasks/openshift_adm_prune_deployments.yml
+++ b/molecule/default/tasks/openshift_adm_prune_deployments.yml
@@ -1,255 +1,255 @@
+---
- name: Prune deployments
block:
- - set_fact:
- dc_name: "hello"
- deployment_ns: "prune-deployments"
- deployment_ns_2: "prune-deployments-2"
-
+ - set_fact:
+ dc_name: "hello"
+ deployment_ns: "prune-deployments"
+ deployment_ns_2: "prune-deployments-2"
- - name: Ensure namespace
- community.okd.k8s:
- kind: Namespace
- name: '{{ deployment_ns }}'
+ - name: Ensure namespace
+ community.okd.k8s:
+ kind: Namespace
+ name: '{{ deployment_ns }}'
- - name: Create deployment config
- community.okd.k8s:
- namespace: '{{ deployment_ns }}'
- definition:
- kind: DeploymentConfig
- apiVersion: apps.openshift.io/v1
- metadata:
- name: '{{ dc_name }}'
- spec:
- replicas: 1
- selector:
+ - name: Create deployment config
+ community.okd.k8s:
+ namespace: '{{ deployment_ns }}'
+ definition:
+ kind: DeploymentConfig
+ apiVersion: apps.openshift.io/v1
+ metadata:
name: '{{ dc_name }}'
- template:
- metadata:
- labels:
- name: '{{ dc_name }}'
- spec:
- containers:
- - name: hello-openshift
- imagePullPolicy: IfNotPresent
- image: python:3.7-alpine
- command: [ "/bin/sh", "-c", "while true;do date;sleep 2s; done"]
- wait: yes
+ spec:
+ replicas: 1
+ selector:
+ name: '{{ dc_name }}'
+ template:
+ metadata:
+ labels:
+ name: '{{ dc_name }}'
+ spec:
+ containers:
+ - name: hello-openshift
+ imagePullPolicy: IfNotPresent
+ image: python:3.7-alpine
+ command: [ "/bin/sh", "-c", "while true;do date;sleep 2s; done"]
+ wait: yes
- - name: prune deployments (no candidate DeploymentConfig)
- community.okd.openshift_adm_prune_deployments:
- namespace: "{{ deployment_ns }}"
- register: test_prune
+ - name: prune deployments (no candidate DeploymentConfig)
+ community.okd.openshift_adm_prune_deployments:
+ namespace: "{{ deployment_ns }}"
+ register: test_prune
- - assert:
- that:
- - test_prune is not changed
- - test_prune.replication_controllers | length == 0
+ - assert:
+ that:
+ - test_prune is not changed
+ - test_prune.replication_controllers | length == 0
- - name: Update DeploymentConfig - set replicas to 0
- community.okd.k8s:
- namespace: "{{ deployment_ns }}"
- definition:
- kind: DeploymentConfig
- apiVersion: "apps.openshift.io/v1"
- metadata:
- name: "{{ dc_name }}"
- spec:
- replicas: 0
- selector:
+ - name: Update DeploymentConfig - set replicas to 0
+ community.okd.k8s:
+ namespace: "{{ deployment_ns }}"
+ definition:
+ kind: DeploymentConfig
+ apiVersion: "apps.openshift.io/v1"
+ metadata:
name: "{{ dc_name }}"
- template:
- metadata:
- labels:
- name: "{{ dc_name }}"
- spec:
- containers:
- - name: hello-openshift
- imagePullPolicy: IfNotPresent
- image: python:3.7-alpine
- command: [ "/bin/sh", "-c", "while true;do date;sleep 2s; done"]
- wait: yes
+ spec:
+ replicas: 0
+ selector:
+ name: "{{ dc_name }}"
+ template:
+ metadata:
+ labels:
+ name: "{{ dc_name }}"
+ spec:
+ containers:
+ - name: hello-openshift
+ imagePullPolicy: IfNotPresent
+ image: python:3.7-alpine
+ command: [ "/bin/sh", "-c", "while true;do date;sleep 2s; done"]
+ wait: yes
- - name: Wait for ReplicationController candidate for pruning
- kubernetes.core.k8s_info:
- kind: ReplicationController
- namespace: "{{ deployment_ns }}"
- register: result
- retries: 10
- delay: 30
- until:
- - result.resources.0.metadata.annotations["openshift.io/deployment.phase"] in ("Failed", "Complete")
+ - name: Wait for ReplicationController candidate for pruning
+ kubernetes.core.k8s_info:
+ kind: ReplicationController
+ namespace: "{{ deployment_ns }}"
+ register: result
+ retries: 10
+ delay: 30
+ until:
+ - result.resources.0.metadata.annotations["openshift.io/deployment.phase"] in ("Failed", "Complete")
- - name: Prune deployments - should delete 1 ReplicationController
- community.okd.openshift_adm_prune_deployments:
- namespace: "{{ deployment_ns }}"
- check_mode: yes
- register: test_prune
+ - name: Prune deployments - should delete 1 ReplicationController
+ community.okd.openshift_adm_prune_deployments:
+ namespace: "{{ deployment_ns }}"
+ check_mode: yes
+ register: test_prune
- - name: Read ReplicationController
- kubernetes.core.k8s_info:
- kind: ReplicationController
- namespace: "{{ deployment_ns }}"
- register: replications
+ - name: Read ReplicationController
+ kubernetes.core.k8s_info:
+ kind: ReplicationController
+ namespace: "{{ deployment_ns }}"
+ register: replications
- - name: Assert that Replication controller was not deleted
- assert:
- that:
- - replications.resources | length == 1
- - 'replications.resources.0.metadata.name is match("{{ dc_name }}-*")'
+ - name: Assert that Replication controller was not deleted
+ assert:
+ that:
+ - replications.resources | length == 1
+ - 'replications.resources.0.metadata.name is match("{{ dc_name }}-*")'
- - name: Assure that candidate ReplicationController was found for pruning
- assert:
- that:
- - test_prune is changed
- - test_prune.replication_controllers | length == 1
- - test_prune.replication_controllers.0.metadata.name == replications.resources.0.metadata.name
- - test_prune.replication_controllers.0.metadata.namespace == replications.resources.0.metadata.namespace
+ - name: Assure that candidate ReplicationController was found for pruning
+ assert:
+ that:
+ - test_prune is changed
+ - test_prune.replication_controllers | length == 1
+ - test_prune.replication_controllers.0.metadata.name == replications.resources.0.metadata.name
+ - test_prune.replication_controllers.0.metadata.namespace == replications.resources.0.metadata.namespace
- - name: Prune deployments - keep younger than 45min (check_mode)
- community.okd.openshift_adm_prune_deployments:
- keep_younger_than: 45
- namespace: "{{ deployment_ns }}"
- check_mode: true
- register: keep_younger
+ - name: Prune deployments - keep younger than 45min (check_mode)
+ community.okd.openshift_adm_prune_deployments:
+ keep_younger_than: 45
+ namespace: "{{ deployment_ns }}"
+ check_mode: true
+ register: keep_younger
- - name: assert no candidate was found
- assert:
- that:
- - keep_younger is not changed
- - keep_younger.replication_controllers == []
+ - name: assert no candidate was found
+ assert:
+ that:
+ - keep_younger is not changed
+ - keep_younger.replication_controllers == []
- - name: Ensure second namespace is created
- community.okd.k8s:
- kind: Namespace
- name: '{{ deployment_ns_2 }}'
+ - name: Ensure second namespace is created
+ community.okd.k8s:
+ kind: Namespace
+ name: '{{ deployment_ns_2 }}'
- - name: Create deployment config from 2nd namespace
- community.okd.k8s:
- namespace: '{{ deployment_ns_2 }}'
- definition:
- kind: DeploymentConfig
- apiVersion: apps.openshift.io/v1
- metadata:
- name: '{{ dc_name }}2'
- spec:
- replicas: 1
- selector:
+ - name: Create deployment config from 2nd namespace
+ community.okd.k8s:
+ namespace: '{{ deployment_ns_2 }}'
+ definition:
+ kind: DeploymentConfig
+ apiVersion: apps.openshift.io/v1
+ metadata:
name: '{{ dc_name }}2'
- template:
- metadata:
- labels:
- name: '{{ dc_name }}2'
- spec:
- containers:
- - name: hello-openshift
- imagePullPolicy: IfNotPresent
- image: python:3.7-alpine
- command: [ "/bin/sh", "-c", "while true;do date;sleep 2s; done"]
- wait: yes
+ spec:
+ replicas: 1
+ selector:
+ name: '{{ dc_name }}2'
+ template:
+ metadata:
+ labels:
+ name: '{{ dc_name }}2'
+ spec:
+ containers:
+ - name: hello-openshift
+ imagePullPolicy: IfNotPresent
+ image: python:3.7-alpine
+ command: [ "/bin/sh", "-c", "while true;do date;sleep 2s; done"]
+ wait: yes
- - name: Stop deployment config - replicas = 0
- community.okd.k8s:
- namespace: '{{ deployment_ns_2 }}'
- definition:
- kind: DeploymentConfig
- apiVersion: apps.openshift.io/v1
- metadata:
- name: '{{ dc_name }}2'
- spec:
- replicas: 0
- selector:
+ - name: Stop deployment config - replicas = 0
+ community.okd.k8s:
+ namespace: '{{ deployment_ns_2 }}'
+ definition:
+ kind: DeploymentConfig
+ apiVersion: apps.openshift.io/v1
+ metadata:
name: '{{ dc_name }}2'
- template:
- metadata:
- labels:
- name: '{{ dc_name }}2'
- spec:
- containers:
- - name: hello-openshift
- imagePullPolicy: IfNotPresent
- image: python:3.7-alpine
- command: [ "/bin/sh", "-c", "while true;do date;sleep 2s; done"]
- wait: yes
+ spec:
+ replicas: 0
+ selector:
+ name: '{{ dc_name }}2'
+ template:
+ metadata:
+ labels:
+ name: '{{ dc_name }}2'
+ spec:
+ containers:
+ - name: hello-openshift
+ imagePullPolicy: IfNotPresent
+ image: python:3.7-alpine
+ command: [ "/bin/sh", "-c", "while true;do date;sleep 2s; done"]
+ wait: yes
- - name: Wait for ReplicationController candidate for pruning
- kubernetes.core.k8s_info:
- kind: ReplicationController
- namespace: "{{ deployment_ns_2 }}"
- register: result
- retries: 10
- delay: 30
- until:
- - result.resources.0.metadata.annotations["openshift.io/deployment.phase"] in ("Failed", "Complete")
+ - name: Wait for ReplicationController candidate for pruning
+ kubernetes.core.k8s_info:
+ kind: ReplicationController
+ namespace: "{{ deployment_ns_2 }}"
+ register: result
+ retries: 10
+ delay: 30
+ until:
+ - result.resources.0.metadata.annotations["openshift.io/deployment.phase"] in ("Failed", "Complete")
- # Prune from one namespace should not have any effect on others namespaces
- - name: Prune deployments from 2nd namespace
- community.okd.openshift_adm_prune_deployments:
- namespace: "{{ deployment_ns_2 }}"
- check_mode: yes
- register: test_prune
+ # Prune from one namespace should not have any effect on others namespaces
+ - name: Prune deployments from 2nd namespace
+ community.okd.openshift_adm_prune_deployments:
+ namespace: "{{ deployment_ns_2 }}"
+ check_mode: yes
+ register: test_prune
- - name: Assure that candidate ReplicationController was found for pruning
- assert:
- that:
- - test_prune is changed
- - test_prune.replication_controllers | length == 1
- - "test_prune.replication_controllers.0.metadata.namespace == deployment_ns_2"
+ - name: Assure that candidate ReplicationController was found for pruning
+ assert:
+ that:
+ - test_prune is changed
+ - test_prune.replication_controllers | length == 1
+ - "test_prune.replication_controllers.0.metadata.namespace == deployment_ns_2"
- # Prune without namespace option
- - name: Prune from all namespace should update more deployments
- community.okd.openshift_adm_prune_deployments:
- check_mode: yes
- register: no_namespace_prune
+ # Prune without namespace option
+ - name: Prune from all namespace should update more deployments
+ community.okd.openshift_adm_prune_deployments:
+ check_mode: yes
+ register: no_namespace_prune
- - name: Assure multiple ReplicationController were found for pruning
- assert:
- that:
- - no_namespace_prune is changed
- - no_namespace_prune.replication_controllers | length == 2
-
- # Execute Prune from 2nd namespace
- - name: Read ReplicationController before Prune operation
- kubernetes.core.k8s_info:
- kind: ReplicationController
- namespace: "{{ deployment_ns_2 }}"
- register: replications
+ - name: Assure multiple ReplicationController were found for pruning
+ assert:
+ that:
+ - no_namespace_prune is changed
+ - no_namespace_prune.replication_controllers | length == 2
- - assert:
- that:
- - replications.resources | length == 1
+ # Execute Prune from 2nd namespace
+ - name: Read ReplicationController before Prune operation
+ kubernetes.core.k8s_info:
+ kind: ReplicationController
+ namespace: "{{ deployment_ns_2 }}"
+ register: replications
- - name: Prune DeploymentConfig from 2nd namespace
- community.okd.openshift_adm_prune_deployments:
- namespace: "{{ deployment_ns_2 }}"
- register: _prune
+ - assert:
+ that:
+ - replications.resources | length == 1
- - name: Assert DeploymentConfig was deleted
- assert:
- that:
- - _prune is changed
- - _prune.replication_controllers | length == 1
- - _prune.replication_controllers.0.details.name == replications.resources.0.metadata.name
+ - name: Prune DeploymentConfig from 2nd namespace
+ community.okd.openshift_adm_prune_deployments:
+ namespace: "{{ deployment_ns_2 }}"
+ register: _prune
- # Execute Prune without namespace option
- - name: Read ReplicationController before Prune operation
- kubernetes.core.k8s_info:
- kind: ReplicationController
- namespace: "{{ deployment_ns }}"
- register: replications
+ - name: Assert DeploymentConfig was deleted
+ assert:
+ that:
+ - _prune is changed
+ - _prune.replication_controllers | length == 1
+ - _prune.replication_controllers.0.details.name == replications.resources.0.metadata.name
- - assert:
- that:
- - replications.resources | length == 1
+ # Execute Prune without namespace option
+ - name: Read ReplicationController before Prune operation
+ kubernetes.core.k8s_info:
+ kind: ReplicationController
+ namespace: "{{ deployment_ns }}"
+ register: replications
- - name: Prune from all namespace should update more deployments
- community.okd.openshift_adm_prune_deployments:
- register: _prune
+ - assert:
+ that:
+ - replications.resources | length == 1
- - name: Assure multiple ReplicationController were found for pruning
- assert:
- that:
- - _prune is changed
- - _prune.replication_controllers | length > 0
+ - name: Prune from all namespace should update more deployments
+ community.okd.openshift_adm_prune_deployments:
+ register: _prune
+
+ - name: Assure multiple ReplicationController were found for pruning
+ assert:
+ that:
+ - _prune is changed
+ - _prune.replication_controllers | length > 0
always:
- name: Delete 1st namespace
diff --git a/molecule/default/tasks/openshift_builds.yml b/molecule/default/tasks/openshift_builds.yml
index b564f8b..2acbac4 100644
--- a/molecule/default/tasks/openshift_builds.yml
+++ b/molecule/default/tasks/openshift_builds.yml
@@ -1,240 +1,245 @@
+---
- block:
- - set_fact:
- build_ns: "builds"
- build_config: "start-build"
- is_name: "ruby"
- prune_build: "prune-build"
+ - set_fact:
+ build_ns: "builds"
+ build_config: "start-build"
+ is_name: "ruby"
+ prune_build: "prune-build"
- - name: Ensure namespace
- kubernetes.core.k8s:
- kind: Namespace
- name: "{{ build_ns }}"
+ - name: Ensure namespace
+ kubernetes.core.k8s:
+ kind: Namespace
+ name: "{{ build_ns }}"
- - name: Create ImageStream
- community.okd.k8s:
- namespace: "{{ build_ns }}"
- definition:
- apiVersion: image.openshift.io/v1
- kind: ImageStream
- metadata:
- name: "{{ is_name }}"
- spec:
- lookupPolicy:
- local: false
- tags: []
+ - name: Create ImageStream
+ community.okd.k8s:
+ namespace: "{{ build_ns }}"
+ definition:
+ apiVersion: image.openshift.io/v1
+ kind: ImageStream
+ metadata:
+ name: "{{ is_name }}"
+ spec:
+ lookupPolicy:
+ local: false
+ tags: []
- - name: Create build configuration
- community.okd.k8s:
- namespace: "{{ build_ns }}"
- definition:
- kind: BuildConfig
- apiVersion: build.openshift.io/v1
- metadata:
- name: "{{ build_config }}"
- spec:
- source:
- dockerfile: |
- FROM openshift/ruby-22-centos7
- RUN sleep 60s
- USER ansible
- strategy:
- type: Docker
- output:
- to:
- kind: "ImageStreamTag"
- name: "{{ is_name }}:latest"
+ - name: Create build configuration
+ community.okd.k8s:
+ namespace: "{{ build_ns }}"
+ definition:
+ kind: BuildConfig
+ apiVersion: build.openshift.io/v1
+ metadata:
+ name: "{{ build_config }}"
+ spec:
+ source:
+ dockerfile: |
+ FROM openshift/ruby-22-centos7
+ RUN sleep 60s
+ USER ansible
+ strategy:
+ type: Docker
+ output:
+ to:
+ kind: "ImageStreamTag"
+ name: "{{ is_name }}:latest"
- - name: Start Build from Build configuration
- community.okd.openshift_build:
- namespace: "{{ build_ns }}"
- build_config_name: "{{ build_config }}"
- register: new_build
+ - name: Start Build from Build configuration
+ community.okd.openshift_build:
+ namespace: "{{ build_ns }}"
+ build_config_name: "{{ build_config }}"
+ register: new_build
- - name: Assert that a build has been created
- assert:
- that:
- - new_build is changed
- - new_build.builds.0.metadata.name == "{{ build_config }}-1"
+ - name: Assert that a build has been created
+ assert:
+ that:
+ - new_build is changed
+ - new_build.builds.0.metadata.name == "{{ build_config }}-1"
- - name: Start a new Build from previous Build
- community.okd.openshift_build:
- namespace: "{{ build_ns }}"
- build_name: "{{ new_build.builds.0.metadata.name }}"
- register: rerun_build
+ - name: Start a new Build from previous Build
+ community.okd.openshift_build:
+ namespace: "{{ build_ns }}"
+ build_name: "{{ new_build.builds.0.metadata.name }}"
+ register: rerun_build
- - name: Assert that another build has been created
- assert:
- that:
- - rerun_build is changed
- - rerun_build.builds.0.metadata.name == "{{ build_config }}-2"
+ - name: Assert that another build has been created
+ assert:
+ that:
+ - rerun_build is changed
+ - rerun_build.builds.0.metadata.name == "{{ build_config }}-2"
- - name: Cancel first build created
- community.okd.openshift_build:
- namespace: "{{ build_ns }}"
- build_name: "{{ build_config }}-1"
- state: cancelled
- wait: yes
- register: cancel
+ - name: Cancel first build created
+ community.okd.openshift_build:
+ namespace: "{{ build_ns }}"
+ build_name: "{{ build_config }}-1"
+ state: cancelled
+ wait: yes
+ register: cancel
- - name: Assert that the Build was cancelled
- assert:
- that:
- - cancel is changed
- - cancel.builds | length == 1
- - cancel.builds.0.metadata.name == "{{ build_config }}-1"
- - cancel.builds.0.metadata.namespace == "{{ build_ns }}"
- - cancel.builds.0.status.cancelled
+ - name: Assert that the Build was cancelled
+ assert:
+ that:
+ - cancel is changed
+ - cancel.builds | length == 1
+ - cancel.builds.0.metadata.name == "{{ build_config }}-1"
+ - cancel.builds.0.metadata.namespace == "{{ build_ns }}"
+ - '"cancelled" in cancel.builds.0.status'
+ - cancel.builds.0.status.cancelled
- - name: Get Build info
- kubernetes.core.k8s_info:
- version: build.openshift.io/v1
- kind: Build
- namespace: "{{ build_ns }}"
- name: "{{ cancel.builds.0.metadata.name }}"
- register: build
+ - name: Get info for 1st Build
+ kubernetes.core.k8s_info:
+ version: build.openshift.io/v1
+ kind: Build
+ namespace: "{{ build_ns }}"
+ name: "{{ cancel.builds.0.metadata.name }}"
+ register: build
- - name: Assert that build phase is cancelled
- assert:
- that:
- - build.resources | length == 1
- - build.resources.0.status.cancelled
- - build.resources.0.status.phase == 'Cancelled'
+ - name: Assert that build phase is cancelled
+ assert:
+ that:
+ - build.resources | length == 1
+ - '"cancelled" in build.resources.0.status'
+ - build.resources.0.status.cancelled
+ - build.resources.0.status.phase == 'Cancelled'
- - name: Cancel and restart Build using build config name
- community.okd.openshift_build:
- namespace: "{{ build_ns }}"
- build_config_name: "{{ build_config }}"
- state: restarted
- build_phases:
- - Running
- - New
- register: restart
+ - name: Cancel and restart Build using build config name
+ community.okd.openshift_build:
+ namespace: "{{ build_ns }}"
+ build_config_name: "{{ build_config }}"
+ state: restarted
+ build_phases:
+ - Pending
+ - Running
+ - New
+ register: restart
- - name: assert that new build was created
- assert:
- that:
- - restart is changed
- - restart.builds | length == 1
- - 'restart.builds.0.metadata.name == "{{ build_config }}-3"'
-
- - name: Get Build 2 info
- kubernetes.core.k8s_info:
- version: build.openshift.io/v1
- kind: Build
- namespace: "{{ build_ns }}"
- name: "{{ build_config }}-2"
- register: build
+ - name: assert that new build was created
+ assert:
+ that:
+ - restart is changed
+ - restart.builds | length == 1
+ - 'restart.builds.0.metadata.name == "{{ build_config }}-3"'
- - name: Assert that build phase is cancelled
- assert:
- that:
- - build.resources | length == 1
- - build.resources.0.status.cancelled
- - build.resources.0.status.phase == 'Cancelled'
+ - name: Get info for 2nd Build
+ kubernetes.core.k8s_info:
+ version: build.openshift.io/v1
+ kind: Build
+ namespace: "{{ build_ns }}"
+ name: "{{ build_config }}-2"
+ register: build
- - name: Get Build info
- kubernetes.core.k8s_info:
- version: build.openshift.io/v1
- kind: Build
- namespace: "{{ build_ns }}"
- name: "{{ build_config }}-3"
- register: build
+ - name: Assert that build phase is cancelled
+ assert:
+ that:
+ - build.resources | length == 1
+ - '"cancelled" in build.resources.0.status'
+ - build.resources.0.status.cancelled
+ - build.resources.0.status.phase == 'Cancelled'
- - name: Assert that Build is not cancelled
- assert:
- that:
- - build.resources | length == 1
- - '"cancelled" not in build.resources.0.status'
- - "build.resources.0.status.phase in ('New', 'Pending', 'Running')"
+ - name: Get info for 3rd build
+ kubernetes.core.k8s_info:
+ version: build.openshift.io/v1
+ kind: Build
+ namespace: "{{ build_ns }}"
+ name: "{{ build_config }}-3"
+ register: build
- - name: Prune Builds keep younger than 30min
- community.okd.openshift_adm_prune_builds:
- keep_younger_than: 30
- namespace: "{{ build_ns }}"
- register: prune
- check_mode: yes
+ - name: Assert that Build is not cancelled
+ assert:
+ that:
+ - build.resources | length == 1
+ - '"cancelled" not in build.resources.0.status'
+ - "build.resources.0.status.phase in ('New', 'Pending', 'Running')"
- - name: Assert that no Builds were found
- assert:
- that:
- - not prune.changed
- - prune.builds | length == 0
+ - name: Prune Builds keep younger than 30min
+ community.okd.openshift_adm_prune_builds:
+ keep_younger_than: 30
+ namespace: "{{ build_ns }}"
+ register: prune
+ check_mode: yes
- - name: Prune Builds without namespace
- community.okd.openshift_adm_prune_builds:
- register: prune_without_ns
- check_mode: yes
+ - name: Assert that no Builds were found
+ assert:
+ that:
+ - not prune.changed
+ - prune.builds | length == 0
- - name: Assert that completed build are candidate for prune
- assert:
- that:
- - prune_without_ns is changed
- - prune_without_ns.builds | length > 0
- - '"{{ build_config }}-1" in build_names'
- - '"{{ build_config }}-2" in build_names'
- vars:
- build_names: '{{ prune_without_ns.builds | map(attribute="metadata") | flatten | map(attribute="name") | list }}'
+ - name: Prune Builds without namespace
+ community.okd.openshift_adm_prune_builds:
+ register: prune_without_ns
+ check_mode: yes
- - name: Prune Builds using namespace
- community.okd.openshift_adm_prune_builds:
- namespace: "{{ build_ns }}"
- register: prune_with_ns
- check_mode: yes
+ - name: Assert that completed build are candidate for prune
+ assert:
+ that:
+ - prune_without_ns is changed
+ - prune_without_ns.builds | length > 0
+ - '"{{ build_config }}-1" in build_names'
+ - '"{{ build_config }}-2" in build_names'
+ vars:
+ build_names: '{{ prune_without_ns.builds | map(attribute="metadata") | flatten | map(attribute="name") | list }}'
- - name: Assert that prune operation found the completed build
- assert:
- that:
- - prune_with_ns is changed
- - prune_with_ns.builds | length == 2
+ - name: Prune Builds using namespace
+ community.okd.openshift_adm_prune_builds:
+ namespace: "{{ build_ns }}"
+ register: prune_with_ns
+ check_mode: yes
- - name: Check Build before prune
- kubernetes.core.k8s_info:
- kind: Build
- api_version: build.openshift.io/v1
- name: "{{ build_config }}-1"
- namespace: "{{ build_ns }}"
- register: resource
+ - name: Assert that prune operation found the completed build
+ assert:
+ that:
+ - prune_with_ns is changed
+ - prune_with_ns.builds | length == 2
- - name: Validate that any previous build operation executed with check_mode did not deleted the build
- assert:
- that:
- - resource.resources | length == 1
+ - name: Check Build before prune
+ kubernetes.core.k8s_info:
+ kind: Build
+ api_version: build.openshift.io/v1
+ name: "{{ build_config }}-1"
+ namespace: "{{ build_ns }}"
+ register: resource
- - name: Execute prune operation
- community.okd.openshift_adm_prune_builds:
- namespace: "{{ build_ns }}"
- register: prune
+ - name: Validate that any previous build operation executed with check_mode did not deleted the build
+ assert:
+ that:
+ - resource.resources | length == 1
- - name: assert prune is changed
- assert:
- that:
- - prune is changed
+ - name: Execute prune operation
+ community.okd.openshift_adm_prune_builds:
+ namespace: "{{ build_ns }}"
+ register: prune
- - name: Check Build
- kubernetes.core.k8s_info:
- kind: Build
- api_version: build.openshift.io/v1
- name: "{{ build_config }}-1"
- namespace: "{{ build_ns }}"
- register: resource
+ - name: assert prune is changed
+ assert:
+ that:
+ - prune is changed
- - name: Assert that the Build does not exist anymore
- assert:
- that:
- - resource.resources | length == 0
+ - name: Check Build
+ kubernetes.core.k8s_info:
+ kind: Build
+ api_version: build.openshift.io/v1
+ name: "{{ build_config }}-1"
+ namespace: "{{ build_ns }}"
+ register: resource
- - name: Check Build
- kubernetes.core.k8s_info:
- kind: Build
- api_version: build.openshift.io/v1
- name: "{{ build_config }}-2"
- namespace: "{{ build_ns }}"
- register: resource
+ - name: Assert that the Build does not exist anymore
+ assert:
+ that:
+ - resource.resources | length == 0
- - name: Assert that the Build does not exist anymore
- assert:
- that:
- - resource.resources | length == 0
+ - name: Check Build
+ kubernetes.core.k8s_info:
+ kind: Build
+ api_version: build.openshift.io/v1
+ name: "{{ build_config }}-2"
+ namespace: "{{ build_ns }}"
+ register: resource
+
+ - name: Assert that the Build does not exist anymore
+ assert:
+ that:
+ - resource.resources | length == 0
always:
- name: Ensure namespace is deleted
diff --git a/molecule/default/tasks/openshift_import_images.yml b/molecule/default/tasks/openshift_import_images.yml
index 04392bb..76c49f0 100644
--- a/molecule/default/tasks/openshift_import_images.yml
+++ b/molecule/default/tasks/openshift_import_images.yml
@@ -1,174 +1,175 @@
+---
- name: Openshift import image testing
block:
- - set_fact:
- test_ns: "import-images"
+ - set_fact:
+ test_ns: "import-images"
- - name: Ensure namespace
- community.okd.k8s:
- kind: Namespace
- name: '{{ test_ns }}'
+ - name: Ensure namespace
+ community.okd.k8s:
+ kind: Namespace
+ name: '{{ test_ns }}'
- - name: Import image using tag (should import latest tag only)
- community.okd.openshift_import_image:
- namespace: "{{ test_ns }}"
- name: "ansible/awx"
- check_mode: yes
- register: import_tag
+ - name: Import image using tag (should import latest tag only)
+ community.okd.openshift_import_image:
+ namespace: "{{ test_ns }}"
+ name: "ansible/awx"
+ check_mode: yes
+ register: import_tag
- - name: Assert only latest was imported
- assert:
- that:
- - import_tag is changed
- - import_tag.result | length == 1
- - import_tag.result.0.spec.import
- - import_tag.result.0.spec.images.0.from.kind == "DockerImage"
- - import_tag.result.0.spec.images.0.from.name == "ansible/awx"
+ - name: Assert only latest was imported
+ assert:
+ that:
+ - import_tag is changed
+ - import_tag.result | length == 1
+ - import_tag.result.0.spec.import
+ - import_tag.result.0.spec.images.0.from.kind == "DockerImage"
+ - import_tag.result.0.spec.images.0.from.name == "ansible/awx"
- - name: check image stream
- kubernetes.core.k8s_info:
- kind: ImageStream
- namespace: "{{ test_ns }}"
- name: awx
- register: resource
-
- - name: assert that image stream is not created when using check_mode=yes
- assert:
- that:
- - resource.resources == []
-
- - name: Import image using tag (should import latest tag only)
- community.okd.openshift_import_image:
- namespace: "{{ test_ns }}"
- name: "ansible/awx"
- register: import_tag
-
- - name: Assert only latest was imported
- assert:
- that:
- - import_tag is changed
-
- - name: check image stream
- kubernetes.core.k8s_info:
- kind: ImageStream
- namespace: "{{ test_ns }}"
- name: awx
- register: resource
-
- - name: assert that image stream contains only tag latest
- assert:
- that:
- - resource.resources | length == 1
- - resource.resources.0.status.tags.0.tag == 'latest'
-
- - name: Import once again the latest tag
- community.okd.openshift_import_image:
- namespace: "{{ test_ns }}"
- name: "ansible/awx"
- register: import_tag
-
- - name: assert change was performed
- assert:
- that:
- - import_tag is changed
-
- - name: check image stream
- kubernetes.core.k8s_info:
- kind: ImageStream
- version: image.openshift.io/v1
- namespace: "{{ test_ns }}"
- name: awx
- register: resource
-
- - name: assert that image stream still contains unique tag
- assert:
- that:
- - resource.resources | length == 1
- - resource.resources.0.status.tags.0.tag == 'latest'
-
- - name: Import another tags
- community.okd.openshift_import_image:
- namespace: "{{ test_ns }}"
- name: "ansible/awx:17.1.0"
- register: import_another_tag
- ignore_errors: yes
-
- - name: assert that another tag was imported
- assert:
- that:
- - import_another_tag is failed
- - '"the tag 17.1.0 does not exist on the image stream" in import_another_tag.msg'
-
- - name: Create simple ImageStream (without docker external container)
- community.okd.k8s:
- namespace: "{{ test_ns }}"
- name: "local-is"
- definition:
- apiVersion: image.openshift.io/v1
+ - name: check image stream
+ kubernetes.core.k8s_info:
kind: ImageStream
- spec:
- lookupPolicy:
- local: false
- tags: []
+ namespace: "{{ test_ns }}"
+ name: awx
+ register: resource
- - name: Import all tag for image stream not pointing on external container image should failed
- community.okd.openshift_import_image:
- namespace: "{{ test_ns }}"
- name: "local-is"
- all: true
- register: error_tag
- ignore_errors: true
- check_mode: yes
+ - name: assert that image stream is not created when using check_mode=yes
+ assert:
+ that:
+ - resource.resources == []
- - name: Assert module cannot import from non-existing tag from ImageStream
- assert:
- that:
- - error_tag is failed
- - 'error_tag.msg == "image stream {{ test_ns }}/local-is does not have tags pointing to external container images"'
+ - name: Import image using tag (should import latest tag only)
+ community.okd.openshift_import_image:
+ namespace: "{{ test_ns }}"
+ name: "ansible/awx"
+ register: import_tag
- - name: import all tags for container image ibmcom/pause and specific tag for redhat/ubi8-micro
- community.okd.openshift_import_image:
- namespace: "{{ test_ns }}"
- name:
- - "ibmcom/pause"
- - "redhat/ubi8-micro:8.5-437"
- all: true
- register: multiple_import
+ - name: Assert only latest was imported
+ assert:
+ that:
+ - import_tag is changed
- - name: Assert that import succeed
- assert:
- that:
- - multiple_import is changed
- - multiple_import.result | length == 2
+ - name: check image stream
+ kubernetes.core.k8s_info:
+ kind: ImageStream
+ namespace: "{{ test_ns }}"
+ name: awx
+ register: resource
- - name: Read ibmcom/pause ImageStream
- kubernetes.core.k8s_info:
- version: image.openshift.io/v1
- kind: ImageStream
- namespace: "{{ test_ns }}"
- name: pause
- register: pause
+ - name: assert that image stream contains only tag latest
+ assert:
+ that:
+ - resource.resources | length == 1
+ - resource.resources.0.status.tags.0.tag == 'latest'
- - name: assert that ibmcom/pause has multiple tags
- assert:
- that:
- - pause.resources | length == 1
- - pause.resources.0.status.tags | length > 1
+ - name: Import once again the latest tag
+ community.okd.openshift_import_image:
+ namespace: "{{ test_ns }}"
+ name: "ansible/awx"
+ register: import_tag
- - name: Read redhat/ubi8-micro ImageStream
- kubernetes.core.k8s_info:
- version: image.openshift.io/v1
- kind: ImageStream
- namespace: "{{ test_ns }}"
- name: ubi8-micro
- register: resource
+ - name: assert change was performed
+ assert:
+ that:
+ - import_tag is changed
- - name: assert that redhat/ubi8-micro has only one tag
- assert:
- that:
- - resource.resources | length == 1
- - resource.resources.0.status.tags | length == 1
- - 'resource.resources.0.status.tags.0.tag == "8.5-437"'
+ - name: check image stream
+ kubernetes.core.k8s_info:
+ kind: ImageStream
+ version: image.openshift.io/v1
+ namespace: "{{ test_ns }}"
+ name: awx
+ register: resource
+
+ - name: assert that image stream still contains unique tag
+ assert:
+ that:
+ - resource.resources | length == 1
+ - resource.resources.0.status.tags.0.tag == 'latest'
+
+ - name: Import another tags
+ community.okd.openshift_import_image:
+ namespace: "{{ test_ns }}"
+ name: "ansible/awx:17.1.0"
+ register: import_another_tag
+ ignore_errors: yes
+
+ - name: assert that another tag was imported
+ assert:
+ that:
+ - import_another_tag is failed
+ - '"the tag 17.1.0 does not exist on the image stream" in import_another_tag.msg'
+
+ - name: Create simple ImageStream (without docker external container)
+ community.okd.k8s:
+ namespace: "{{ test_ns }}"
+ name: "local-is"
+ definition:
+ apiVersion: image.openshift.io/v1
+ kind: ImageStream
+ spec:
+ lookupPolicy:
+ local: false
+ tags: []
+
+ - name: Import all tag for image stream not pointing on external container image should failed
+ community.okd.openshift_import_image:
+ namespace: "{{ test_ns }}"
+ name: "local-is"
+ all: true
+ register: error_tag
+ ignore_errors: true
+ check_mode: yes
+
+ - name: Assert module cannot import from non-existing tag from ImageStream
+ assert:
+ that:
+ - error_tag is failed
+ - 'error_tag.msg == "image stream {{ test_ns }}/local-is does not have tags pointing to external container images"'
+
+ - name: import all tags for container image ibmcom/pause and specific tag for redhat/ubi8-micro
+ community.okd.openshift_import_image:
+ namespace: "{{ test_ns }}"
+ name:
+ - "ibmcom/pause"
+ - "redhat/ubi8-micro:8.5-437"
+ all: true
+ register: multiple_import
+
+ - name: Assert that import succeed
+ assert:
+ that:
+ - multiple_import is changed
+ - multiple_import.result | length == 2
+
+ - name: Read ibmcom/pause ImageStream
+ kubernetes.core.k8s_info:
+ version: image.openshift.io/v1
+ kind: ImageStream
+ namespace: "{{ test_ns }}"
+ name: pause
+ register: pause
+
+ - name: assert that ibmcom/pause has multiple tags
+ assert:
+ that:
+ - pause.resources | length == 1
+ - pause.resources.0.status.tags | length > 1
+
+ - name: Read redhat/ubi8-micro ImageStream
+ kubernetes.core.k8s_info:
+ version: image.openshift.io/v1
+ kind: ImageStream
+ namespace: "{{ test_ns }}"
+ name: ubi8-micro
+ register: resource
+
+ - name: assert that redhat/ubi8-micro has only one tag
+ assert:
+ that:
+ - resource.resources | length == 1
+ - resource.resources.0.status.tags | length == 1
+ - 'resource.resources.0.status.tags.0.tag == "8.5-437"'
always:
- name: Delete testing namespace
diff --git a/molecule/default/tasks/openshift_prune_images.yml b/molecule/default/tasks/openshift_prune_images.yml
index 86630da..1748522 100644
--- a/molecule/default/tasks/openshift_prune_images.yml
+++ b/molecule/default/tasks/openshift_prune_images.yml
@@ -38,12 +38,12 @@
name: "{{ pod_name }}"
spec:
containers:
- - name: test-container
- image: "{{ prune_registry }}/{{ prune_ns }}/{{ container.name }}:latest"
- command:
- - /bin/sh
- - -c
- - while true;do date;sleep 5; done
+ - name: test-container
+ image: "{{ prune_registry }}/{{ prune_ns }}/{{ container.name }}:latest"
+ command:
+ - /bin/sh
+ - -c
+ - while true;do date;sleep 5; done
- name: Create limit range for images size
community.okd.k8s:
@@ -57,7 +57,7 @@
- type: openshift.io/Image
max:
storage: 1Gi
-
+
- name: Prune images from namespace
community.okd.openshift_adm_prune_images:
registry_url: "{{ prune_registry }}"
diff --git a/molecule/default/tasks/openshift_route.yml b/molecule/default/tasks/openshift_route.yml
index 50056b7..b3043cb 100644
--- a/molecule/default/tasks/openshift_route.yml
+++ b/molecule/default/tasks/openshift_route.yml
@@ -19,10 +19,10 @@
app: hello-kubernetes
spec:
containers:
- - name: hello-kubernetes
- image: docker.io/openshift/hello-openshift
- ports:
- - containerPort: 8080
+ - name: hello-kubernetes
+ image: docker.io/openshift/hello-openshift
+ ports:
+ - containerPort: 8080
- name: Create Service
community.okd.k8s:
@@ -35,8 +35,8 @@
namespace: default
spec:
ports:
- - port: 80
- targetPort: 8080
+ - port: 80
+ targetPort: 8080
selector:
app: hello-kubernetes
diff --git a/molecule/default/vars/main.yml b/molecule/default/vars/main.yml
index 66fb0d3..22e227c 100644
--- a/molecule/default/vars/main.yml
+++ b/molecule/default/vars/main.yml
@@ -64,14 +64,16 @@ okd_dc_triggers:
okd_dc_spec:
template: '{{ k8s_pod_template }}'
- triggers: '{{ okd_dc_triggers }}'
+ selector:
+ matchLabels:
+ app: "{{ k8s_pod_name }}"
replicas: 1
strategy:
type: Recreate
okd_dc_template:
- apiVersion: v1
- kind: DeploymentConfig
+ apiVersion: apps/v1
+ kind: Deployment
spec: '{{ okd_dc_spec }}'
okd_imagestream_template:
@@ -83,12 +85,12 @@ okd_imagestream_template:
lookupPolicy:
local: true
tags:
- - annotations: null
- from:
- kind: DockerImage
- name: '{{ image }}'
- name: '{{ image_tag }}'
- referencePolicy:
- type: Source
+ - annotations: null
+ from:
+ kind: DockerImage
+ name: '{{ image }}'
+ name: '{{ image_tag }}'
+ referencePolicy:
+ type: Source
image_tag: latest
diff --git a/plugins/connection/oc.py b/plugins/connection/oc.py
index 44236a1..ae399e6 100644
--- a/plugins/connection/oc.py
+++ b/plugins/connection/oc.py
@@ -17,10 +17,11 @@
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see .
-from __future__ import (absolute_import, division, print_function)
+from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
-DOCUMENTATION = '''
+DOCUMENTATION = """
author:
- xuxinkun (@xuxinkun)
@@ -145,29 +146,32 @@ DOCUMENTATION = '''
env:
- name: K8S_AUTH_VERIFY_SSL
aliases: [ oc_verify_ssl ]
-'''
+"""
-from ansible_collections.kubernetes.core.plugins.connection.kubectl import Connection as KubectlConnection
+from ansible_collections.kubernetes.core.plugins.connection.kubectl import (
+ Connection as KubectlConnection,
+)
-CONNECTION_TRANSPORT = 'oc'
+CONNECTION_TRANSPORT = "oc"
CONNECTION_OPTIONS = {
- 'oc_container': '-c',
- 'oc_namespace': '-n',
- 'oc_kubeconfig': '--kubeconfig',
- 'oc_context': '--context',
- 'oc_host': '--server',
- 'client_cert': '--client-certificate',
- 'client_key': '--client-key',
- 'ca_cert': '--certificate-authority',
- 'validate_certs': '--insecure-skip-tls-verify',
- 'oc_token': '--token'
+ "oc_container": "-c",
+ "oc_namespace": "-n",
+ "oc_kubeconfig": "--kubeconfig",
+ "oc_context": "--context",
+ "oc_host": "--server",
+ "client_cert": "--client-certificate",
+ "client_key": "--client-key",
+ "ca_cert": "--certificate-authority",
+ "validate_certs": "--insecure-skip-tls-verify",
+ "oc_token": "--token",
}
class Connection(KubectlConnection):
- ''' Local oc based connections '''
+ """Local oc based connections"""
+
transport = CONNECTION_TRANSPORT
connection_options = CONNECTION_OPTIONS
documentation = DOCUMENTATION
diff --git a/plugins/inventory/openshift.py b/plugins/inventory/openshift.py
index 940a585..4ec7884 100644
--- a/plugins/inventory/openshift.py
+++ b/plugins/inventory/openshift.py
@@ -1,11 +1,11 @@
# Copyright (c) 2018 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-from __future__ import (absolute_import, division, print_function)
+from __future__ import absolute_import, division, print_function
__metaclass__ = type
-DOCUMENTATION = '''
+DOCUMENTATION = """
name: openshift
author:
- Chris Houseknecht (@chouseknecht)
@@ -94,34 +94,41 @@ DOCUMENTATION = '''
- "python >= 3.6"
- "kubernetes >= 12.0.0"
- "PyYAML >= 3.11"
-'''
+"""
-EXAMPLES = '''
+EXAMPLES = """
# File must be named openshift.yaml or openshift.yml
-# Authenticate with token, and return all pods and services for all namespaces
-plugin: community.okd.openshift
-connections:
- - host: https://192.168.64.4:8443
- api_key: xxxxxxxxxxxxxxxx
- verify_ssl: false
+- name: Authenticate with token, and return all pods and services for all namespaces
+ plugin: community.okd.openshift
+ connections:
+ - host: https://192.168.64.4:8443
+ api_key: xxxxxxxxxxxxxxxx
+ verify_ssl: false
-# Use default config (~/.kube/config) file and active context, and return objects for a specific namespace
-plugin: community.okd.openshift
-connections:
- - namespaces:
- - testing
+- name: Use default config (~/.kube/config) file and active context, and return objects for a specific namespace
+ plugin: community.okd.openshift
+ connections:
+ - namespaces:
+ - testing
-# Use a custom config file, and a specific context.
-plugin: community.okd.openshift
-connections:
- - kubeconfig: /path/to/config
- context: 'awx/192-168-64-4:8443/developer'
-'''
+- name: Use a custom config file, and a specific context.
+ plugin: community.okd.openshift
+ connections:
+ - kubeconfig: /path/to/config
+ context: 'awx/192-168-64-4:8443/developer'
+"""
try:
- from ansible_collections.kubernetes.core.plugins.inventory.k8s import K8sInventoryException, InventoryModule as K8sInventoryModule, format_dynamic_api_exc
- from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import get_api_client
+ from ansible_collections.kubernetes.core.plugins.inventory.k8s import (
+ K8sInventoryException,
+ InventoryModule as K8sInventoryModule,
+ format_dynamic_api_exc,
+ )
+ from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
+ get_api_client,
+ )
+
HAS_KUBERNETES_COLLECTION = True
except ImportError as e:
HAS_KUBERNETES_COLLECTION = False
@@ -134,22 +141,26 @@ except ImportError:
class InventoryModule(K8sInventoryModule):
- NAME = 'community.okd.openshift'
+ NAME = "community.okd.openshift"
- connection_plugin = 'community.okd.oc'
- transport = 'oc'
+ connection_plugin = "community.okd.oc"
+ transport = "oc"
def check_kubernetes_collection(self):
-
if not HAS_KUBERNETES_COLLECTION:
- K8sInventoryException("The kubernetes.core collection must be installed")
+ raise K8sInventoryException(
+ "The kubernetes.core collection must be installed"
+ )
def fetch_objects(self, connections):
self.check_kubernetes_collection()
super(InventoryModule, self).fetch_objects(connections)
- self.display.deprecated("The 'openshift' inventory plugin has been deprecated and will be removed in release 4.0.0",
- version='4.0.0', collection_name='community.okd')
+ self.display.deprecated(
+ "The 'openshift' inventory plugin has been deprecated and will be removed in release 4.0.0",
+ version="4.0.0",
+ collection_name="community.okd",
+ )
if connections:
if not isinstance(connections, list):
@@ -157,9 +168,11 @@ class InventoryModule(K8sInventoryModule):
for connection in connections:
client = get_api_client(**connection)
- name = connection.get('name', self.get_default_host_name(client.configuration.host))
- if connection.get('namespaces'):
- namespaces = connection['namespaces']
+ name = connection.get(
+ "name", self.get_default_host_name(client.configuration.host)
+ )
+ if connection.get("namespaces"):
+ namespaces = connection["namespaces"]
else:
namespaces = self.get_available_namespaces(client)
for namespace in namespaces:
@@ -173,15 +186,19 @@ class InventoryModule(K8sInventoryModule):
def get_routes_for_namespace(self, client, name, namespace):
self.check_kubernetes_collection()
- v1_route = client.resources.get(api_version='route.openshift.io/v1', kind='Route')
+ v1_route = client.resources.get(
+ api_version="route.openshift.io/v1", kind="Route"
+ )
try:
obj = v1_route.get(namespace=namespace)
except DynamicApiError as exc:
self.display.debug(exc)
- raise K8sInventoryException('Error fetching Routes list: %s' % format_dynamic_api_exc(exc))
+ raise K8sInventoryException(
+ "Error fetching Routes list: %s" % format_dynamic_api_exc(exc)
+ )
- namespace_group = 'namespace_{0}'.format(namespace)
- namespace_routes_group = '{0}_routes'.format(namespace_group)
+ namespace_group = "namespace_{0}".format(namespace)
+ namespace_routes_group = "{0}_routes".format(namespace_group)
self.inventory.add_group(name)
self.inventory.add_group(namespace_group)
@@ -190,14 +207,18 @@ class InventoryModule(K8sInventoryModule):
self.inventory.add_child(namespace_group, namespace_routes_group)
for route in obj.items:
route_name = route.metadata.name
- route_annotations = {} if not route.metadata.annotations else dict(route.metadata.annotations)
+ route_annotations = (
+ {}
+ if not route.metadata.annotations
+ else dict(route.metadata.annotations)
+ )
self.inventory.add_host(route_name)
if route.metadata.labels:
# create a group for each label_value
for key, value in route.metadata.labels:
- group_name = 'label_{0}_{1}'.format(key, value)
+ group_name = "label_{0}_{1}".format(key, value)
self.inventory.add_group(group_name)
self.inventory.add_child(group_name, route_name)
route_labels = dict(route.metadata.labels)
@@ -207,19 +228,25 @@ class InventoryModule(K8sInventoryModule):
self.inventory.add_child(namespace_routes_group, route_name)
# add hostvars
- self.inventory.set_variable(route_name, 'labels', route_labels)
- self.inventory.set_variable(route_name, 'annotations', route_annotations)
- self.inventory.set_variable(route_name, 'cluster_name', route.metadata.clusterName)
- self.inventory.set_variable(route_name, 'object_type', 'route')
- self.inventory.set_variable(route_name, 'self_link', route.metadata.selfLink)
- self.inventory.set_variable(route_name, 'resource_version', route.metadata.resourceVersion)
- self.inventory.set_variable(route_name, 'uid', route.metadata.uid)
+ self.inventory.set_variable(route_name, "labels", route_labels)
+ self.inventory.set_variable(route_name, "annotations", route_annotations)
+ self.inventory.set_variable(
+ route_name, "cluster_name", route.metadata.clusterName
+ )
+ self.inventory.set_variable(route_name, "object_type", "route")
+ self.inventory.set_variable(
+ route_name, "self_link", route.metadata.selfLink
+ )
+ self.inventory.set_variable(
+ route_name, "resource_version", route.metadata.resourceVersion
+ )
+ self.inventory.set_variable(route_name, "uid", route.metadata.uid)
if route.spec.host:
- self.inventory.set_variable(route_name, 'host', route.spec.host)
+ self.inventory.set_variable(route_name, "host", route.spec.host)
if route.spec.path:
- self.inventory.set_variable(route_name, 'path', route.spec.path)
+ self.inventory.set_variable(route_name, "path", route.spec.path)
- if hasattr(route.spec.port, 'targetPort') and route.spec.port.targetPort:
- self.inventory.set_variable(route_name, 'port', dict(route.spec.port))
+ if hasattr(route.spec.port, "targetPort") and route.spec.port.targetPort:
+ self.inventory.set_variable(route_name, "port", dict(route.spec.port))
diff --git a/plugins/module_utils/k8s.py b/plugins/module_utils/k8s.py
index 87ec70d..9c8f47f 100644
--- a/plugins/module_utils/k8s.py
+++ b/plugins/module_utils/k8s.py
@@ -1,35 +1,46 @@
#!/usr/bin/env python
-from __future__ import (absolute_import, division, print_function)
+from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
import re
import operator
from functools import reduce
-from ansible_collections.community.okd.plugins.module_utils.openshift_common import AnsibleOpenshiftModule
+from ansible_collections.community.okd.plugins.module_utils.openshift_common import (
+ AnsibleOpenshiftModule,
+)
try:
- from ansible_collections.kubernetes.core.plugins.module_utils.k8s.resource import create_definitions
- from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import CoreException
+ from ansible_collections.kubernetes.core.plugins.module_utils.k8s.resource import (
+ create_definitions,
+ )
+ from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import (
+ CoreException,
+ )
except ImportError:
pass
from ansible.module_utils._text import to_native
try:
- from kubernetes.dynamic.exceptions import DynamicApiError, NotFoundError, ForbiddenError
+ from kubernetes.dynamic.exceptions import (
+ DynamicApiError,
+ NotFoundError,
+ ForbiddenError,
+ )
except ImportError as e:
pass
-TRIGGER_ANNOTATION = 'image.openshift.io/triggers'
-TRIGGER_CONTAINER = re.compile(r"(?P.*)\[((?P[0-9]+)|\?\(@\.name==[\"'\\]*(?P[a-z0-9]([-a-z0-9]*[a-z0-9])?))")
+TRIGGER_ANNOTATION = "image.openshift.io/triggers"
+TRIGGER_CONTAINER = re.compile(
+ r"(?P.*)\[((?P[0-9]+)|\?\(@\.name==[\"'\\]*(?P[a-z0-9]([-a-z0-9]*[a-z0-9])?))"
+)
class OKDRawModule(AnsibleOpenshiftModule):
-
def __init__(self, **kwargs):
-
super(OKDRawModule, self).__init__(**kwargs)
@property
@@ -50,36 +61,60 @@ class OKDRawModule(AnsibleOpenshiftModule):
result = {"changed": False, "result": {}}
warnings = []
- if self.params.get("state") != 'absent':
+ if self.params.get("state") != "absent":
existing = None
name = definition.get("metadata", {}).get("name")
namespace = definition.get("metadata", {}).get("namespace")
- if definition.get("kind") in ['Project', 'ProjectRequest']:
+ if definition.get("kind") in ["Project", "ProjectRequest"]:
try:
- resource = self.svc.find_resource(kind=definition.get("kind"), api_version=definition.get("apiVersion", "v1"))
- existing = resource.get(name=name, namespace=namespace).to_dict()
+ resource = self.svc.find_resource(
+ kind=definition.get("kind"),
+ api_version=definition.get("apiVersion", "v1"),
+ )
+ existing = resource.get(
+ name=name, namespace=namespace
+ ).to_dict()
except (NotFoundError, ForbiddenError):
result = self.create_project_request(definition)
changed |= result["changed"]
results.append(result)
continue
except DynamicApiError as exc:
- self.fail_json(msg='Failed to retrieve requested object: {0}'.format(exc.body),
- error=exc.status, status=exc.status, reason=exc.reason)
+ self.fail_json(
+ msg="Failed to retrieve requested object: {0}".format(
+ exc.body
+ ),
+ error=exc.status,
+ status=exc.status,
+ reason=exc.reason,
+ )
- if definition.get("kind") not in ['Project', 'ProjectRequest']:
+ if definition.get("kind") not in ["Project", "ProjectRequest"]:
try:
- resource = self.svc.find_resource(kind=definition.get("kind"), api_version=definition.get("apiVersion", "v1"))
- existing = resource.get(name=name, namespace=namespace).to_dict()
+ resource = self.svc.find_resource(
+ kind=definition.get("kind"),
+ api_version=definition.get("apiVersion", "v1"),
+ )
+ existing = resource.get(
+ name=name, namespace=namespace
+ ).to_dict()
except Exception:
existing = None
if existing:
- if resource.kind == 'DeploymentConfig':
- if definition.get('spec', {}).get('triggers'):
- definition = self.resolve_imagestream_triggers(existing, definition)
- elif existing['metadata'].get('annotations', {}).get(TRIGGER_ANNOTATION):
- definition = self.resolve_imagestream_trigger_annotation(existing, definition)
+ if resource.kind == "DeploymentConfig":
+ if definition.get("spec", {}).get("triggers"):
+ definition = self.resolve_imagestream_triggers(
+ existing, definition
+ )
+ elif (
+ existing["metadata"]
+ .get("annotations", {})
+ .get(TRIGGER_ANNOTATION)
+ ):
+ definition = self.resolve_imagestream_trigger_annotation(
+ existing, definition
+ )
if self.params.get("validate") is not None:
warnings = self.validate(definition)
@@ -116,13 +151,15 @@ class OKDRawModule(AnsibleOpenshiftModule):
@staticmethod
def get_index(desired, objects, keys):
- """ Iterates over keys, returns the first object from objects where the value of the key
- matches the value in desired
+ """Iterates over keys, returns the first object from objects where the value of the key
+ matches the value in desired
"""
# pylint: disable=use-a-generator
# Use a generator instead 'all(desired.get(key, True) == item.get(key, False) for key in keys)'
for i, item in enumerate(objects):
- if item and all([desired.get(key, True) == item.get(key, False) for key in keys]):
+ if item and all(
+ [desired.get(key, True) == item.get(key, False) for key in keys]
+ ):
return i
def resolve_imagestream_trigger_annotation(self, existing, definition):
@@ -137,84 +174,148 @@ class OKDRawModule(AnsibleOpenshiftModule):
def set_from_fields(d, fields, value):
get_from_fields(d, fields[:-1])[fields[-1]] = value
- if TRIGGER_ANNOTATION in definition['metadata'].get('annotations', {}).keys():
- triggers = yaml.safe_load(definition['metadata']['annotations'][TRIGGER_ANNOTATION] or '[]')
+ if TRIGGER_ANNOTATION in definition["metadata"].get("annotations", {}).keys():
+ triggers = yaml.safe_load(
+ definition["metadata"]["annotations"][TRIGGER_ANNOTATION] or "[]"
+ )
else:
- triggers = yaml.safe_load(existing['metadata'].get('annotations', '{}').get(TRIGGER_ANNOTATION, '[]'))
+ triggers = yaml.safe_load(
+ existing["metadata"]
+ .get("annotations", "{}")
+ .get(TRIGGER_ANNOTATION, "[]")
+ )
if not isinstance(triggers, list):
return definition
for trigger in triggers:
- if trigger.get('fieldPath'):
- parsed = self.parse_trigger_fieldpath(trigger['fieldPath'])
- path = parsed.get('path', '').split('.')
+ if trigger.get("fieldPath"):
+ parsed = self.parse_trigger_fieldpath(trigger["fieldPath"])
+ path = parsed.get("path", "").split(".")
if path:
existing_containers = get_from_fields(existing, path)
new_containers = get_from_fields(definition, path)
- if parsed.get('name'):
- existing_index = self.get_index({'name': parsed['name']}, existing_containers, ['name'])
- new_index = self.get_index({'name': parsed['name']}, new_containers, ['name'])
- elif parsed.get('index') is not None:
- existing_index = new_index = int(parsed['index'])
+ if parsed.get("name"):
+ existing_index = self.get_index(
+ {"name": parsed["name"]}, existing_containers, ["name"]
+ )
+ new_index = self.get_index(
+ {"name": parsed["name"]}, new_containers, ["name"]
+ )
+ elif parsed.get("index") is not None:
+ existing_index = new_index = int(parsed["index"])
else:
existing_index = new_index = None
if existing_index is not None and new_index is not None:
- if existing_index < len(existing_containers) and new_index < len(new_containers):
- set_from_fields(definition, path + [new_index, 'image'], get_from_fields(existing, path + [existing_index, 'image']))
+ if existing_index < len(
+ existing_containers
+ ) and new_index < len(new_containers):
+ set_from_fields(
+ definition,
+ path + [new_index, "image"],
+ get_from_fields(
+ existing, path + [existing_index, "image"]
+ ),
+ )
return definition
def resolve_imagestream_triggers(self, existing, definition):
-
- existing_triggers = existing.get('spec', {}).get('triggers')
- new_triggers = definition['spec']['triggers']
- existing_containers = existing.get('spec', {}).get('template', {}).get('spec', {}).get('containers', [])
- new_containers = definition.get('spec', {}).get('template', {}).get('spec', {}).get('containers', [])
+ existing_triggers = existing.get("spec", {}).get("triggers")
+ new_triggers = definition["spec"]["triggers"]
+ existing_containers = (
+ existing.get("spec", {})
+ .get("template", {})
+ .get("spec", {})
+ .get("containers", [])
+ )
+ new_containers = (
+ definition.get("spec", {})
+ .get("template", {})
+ .get("spec", {})
+ .get("containers", [])
+ )
for i, trigger in enumerate(new_triggers):
- if trigger.get('type') == 'ImageChange' and trigger.get('imageChangeParams'):
- names = trigger['imageChangeParams'].get('containerNames', [])
+ if trigger.get("type") == "ImageChange" and trigger.get(
+ "imageChangeParams"
+ ):
+ names = trigger["imageChangeParams"].get("containerNames", [])
for name in names:
- old_container_index = self.get_index({'name': name}, existing_containers, ['name'])
- new_container_index = self.get_index({'name': name}, new_containers, ['name'])
- if old_container_index is not None and new_container_index is not None:
- image = existing['spec']['template']['spec']['containers'][old_container_index]['image']
- definition['spec']['template']['spec']['containers'][new_container_index]['image'] = image
+ old_container_index = self.get_index(
+ {"name": name}, existing_containers, ["name"]
+ )
+ new_container_index = self.get_index(
+ {"name": name}, new_containers, ["name"]
+ )
+ if (
+ old_container_index is not None
+ and new_container_index is not None
+ ):
+ image = existing["spec"]["template"]["spec"]["containers"][
+ old_container_index
+ ]["image"]
+ definition["spec"]["template"]["spec"]["containers"][
+ new_container_index
+ ]["image"] = image
- existing_index = self.get_index(trigger['imageChangeParams'],
- [x.get('imageChangeParams') for x in existing_triggers],
- ['containerNames'])
+ existing_index = self.get_index(
+ trigger["imageChangeParams"],
+ [x.get("imageChangeParams") for x in existing_triggers],
+ ["containerNames"],
+ )
if existing_index is not None:
- existing_image = existing_triggers[existing_index].get('imageChangeParams', {}).get('lastTriggeredImage')
+ existing_image = (
+ existing_triggers[existing_index]
+ .get("imageChangeParams", {})
+ .get("lastTriggeredImage")
+ )
if existing_image:
- definition['spec']['triggers'][i]['imageChangeParams']['lastTriggeredImage'] = existing_image
- existing_from = existing_triggers[existing_index].get('imageChangeParams', {}).get('from', {})
- new_from = trigger['imageChangeParams'].get('from', {})
- existing_namespace = existing_from.get('namespace')
- existing_name = existing_from.get('name', False)
- new_name = new_from.get('name', True)
- add_namespace = existing_namespace and 'namespace' not in new_from.keys() and existing_name == new_name
+ definition["spec"]["triggers"][i]["imageChangeParams"][
+ "lastTriggeredImage"
+ ] = existing_image
+ existing_from = (
+ existing_triggers[existing_index]
+ .get("imageChangeParams", {})
+ .get("from", {})
+ )
+ new_from = trigger["imageChangeParams"].get("from", {})
+ existing_namespace = existing_from.get("namespace")
+ existing_name = existing_from.get("name", False)
+ new_name = new_from.get("name", True)
+ add_namespace = (
+ existing_namespace
+ and "namespace" not in new_from.keys()
+ and existing_name == new_name
+ )
if add_namespace:
- definition['spec']['triggers'][i]['imageChangeParams']['from']['namespace'] = existing_from['namespace']
+ definition["spec"]["triggers"][i]["imageChangeParams"][
+ "from"
+ ]["namespace"] = existing_from["namespace"]
return definition
def parse_trigger_fieldpath(self, expression):
parsed = TRIGGER_CONTAINER.search(expression).groupdict()
- if parsed.get('index'):
- parsed['index'] = int(parsed['index'])
+ if parsed.get("index"):
+ parsed["index"] = int(parsed["index"])
return parsed
def create_project_request(self, definition):
- definition['kind'] = 'ProjectRequest'
- result = {'changed': False, 'result': {}}
- resource = self.svc.find_resource(kind='ProjectRequest', api_version=definition['apiVersion'], fail=True)
+ definition["kind"] = "ProjectRequest"
+ result = {"changed": False, "result": {}}
+ resource = self.svc.find_resource(
+ kind="ProjectRequest", api_version=definition["apiVersion"], fail=True
+ )
if not self.check_mode:
try:
k8s_obj = resource.create(definition)
- result['result'] = k8s_obj.to_dict()
+ result["result"] = k8s_obj.to_dict()
except DynamicApiError as exc:
- self.fail_json(msg="Failed to create object: {0}".format(exc.body),
- error=exc.status, status=exc.status, reason=exc.reason)
- result['changed'] = True
- result['method'] = 'create'
+ self.fail_json(
+ msg="Failed to create object: {0}".format(exc.body),
+ error=exc.status,
+ status=exc.status,
+ reason=exc.reason,
+ )
+ result["changed"] = True
+ result["method"] = "create"
return result
diff --git a/plugins/module_utils/openshift_adm_prune_auth.py b/plugins/module_utils/openshift_adm_prune_auth.py
index e5143ae..f286405 100644
--- a/plugins/module_utils/openshift_adm_prune_auth.py
+++ b/plugins/module_utils/openshift_adm_prune_auth.py
@@ -1,11 +1,14 @@
#!/usr/bin/env python
-from __future__ import (absolute_import, division, print_function)
+from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
from ansible.module_utils._text import to_native
-from ansible_collections.community.okd.plugins.module_utils.openshift_common import AnsibleOpenshiftModule
+from ansible_collections.community.okd.plugins.module_utils.openshift_common import (
+ AnsibleOpenshiftModule,
+)
try:
from kubernetes import client
@@ -18,31 +21,36 @@ class OpenShiftAdmPruneAuth(AnsibleOpenshiftModule):
def __init__(self, **kwargs):
super(OpenShiftAdmPruneAuth, self).__init__(**kwargs)
- def prune_resource_binding(self, kind, api_version, ref_kind, ref_namespace_names, propagation_policy=None):
-
+ def prune_resource_binding(
+ self, kind, api_version, ref_kind, ref_namespace_names, propagation_policy=None
+ ):
resource = self.find_resource(kind=kind, api_version=api_version, fail=True)
candidates = []
for ref_namespace, ref_name in ref_namespace_names:
try:
result = resource.get(name=None, namespace=ref_namespace)
result = result.to_dict()
- result = result.get('items') if 'items' in result else [result]
+ result = result.get("items") if "items" in result else [result]
for obj in result:
- namespace = obj['metadata'].get('namespace', None)
- name = obj['metadata'].get('name')
- if ref_kind and obj['roleRef']['kind'] != ref_kind:
+ namespace = obj["metadata"].get("namespace", None)
+ name = obj["metadata"].get("name")
+ if ref_kind and obj["roleRef"]["kind"] != ref_kind:
# skip this binding as the roleRef.kind does not match
continue
- if obj['roleRef']['name'] == ref_name:
+ if obj["roleRef"]["name"] == ref_name:
# select this binding as the roleRef.name match
candidates.append((namespace, name))
except NotFoundError:
continue
except DynamicApiError as exc:
- msg = "Failed to get {kind} resource due to: {msg}".format(kind=kind, msg=exc.body)
+ msg = "Failed to get {kind} resource due to: {msg}".format(
+ kind=kind, msg=exc.body
+ )
self.fail_json(msg=msg)
except Exception as e:
- msg = "Failed to get {kind} due to: {msg}".format(kind=kind, msg=to_native(e))
+ msg = "Failed to get {kind} due to: {msg}".format(
+ kind=kind, msg=to_native(e)
+ )
self.fail_json(msg=msg)
if len(candidates) == 0 or self.check_mode:
@@ -54,24 +62,29 @@ class OpenShiftAdmPruneAuth(AnsibleOpenshiftModule):
for namespace, name in candidates:
try:
- result = resource.delete(name=name, namespace=namespace, body=delete_options)
+ result = resource.delete(
+ name=name, namespace=namespace, body=delete_options
+ )
except DynamicApiError as exc:
- msg = "Failed to delete {kind} {namespace}/{name} due to: {msg}".format(kind=kind, namespace=namespace, name=name, msg=exc.body)
+ msg = "Failed to delete {kind} {namespace}/{name} due to: {msg}".format(
+ kind=kind, namespace=namespace, name=name, msg=exc.body
+ )
self.fail_json(msg=msg)
except Exception as e:
- msg = "Failed to delete {kind} {namespace}/{name} due to: {msg}".format(kind=kind, namespace=namespace, name=name, msg=to_native(e))
+ msg = "Failed to delete {kind} {namespace}/{name} due to: {msg}".format(
+ kind=kind, namespace=namespace, name=name, msg=to_native(e)
+ )
self.fail_json(msg=msg)
return [y if x is None else x + "/" + y for x, y in candidates]
def update_resource_binding(self, ref_kind, ref_names, namespaced=False):
-
- kind = 'ClusterRoleBinding'
- api_version = "rbac.authorization.k8s.io/v1",
+ kind = "ClusterRoleBinding"
+ api_version = "rbac.authorization.k8s.io/v1"
if namespaced:
kind = "RoleBinding"
resource = self.find_resource(kind=kind, api_version=api_version, fail=True)
result = resource.get(name=None, namespace=None).to_dict()
- result = result.get('items') if 'items' in result else [result]
+ result = result.get("items") if "items" in result else [result]
if len(result) == 0:
return [], False
@@ -79,29 +92,40 @@ class OpenShiftAdmPruneAuth(AnsibleOpenshiftModule):
def _update_user_group(binding_namespace, subjects):
users, groups = [], []
for x in subjects:
- if x['kind'] == 'User':
- users.append(x['name'])
- elif x['kind'] == 'Group':
- groups.append(x['name'])
- elif x['kind'] == 'ServiceAccount':
+ if x["kind"] == "User":
+ users.append(x["name"])
+ elif x["kind"] == "Group":
+ groups.append(x["name"])
+ elif x["kind"] == "ServiceAccount":
namespace = binding_namespace
- if x.get('namespace') is not None:
- namespace = x.get('namespace')
+ if x.get("namespace") is not None:
+ namespace = x.get("namespace")
if namespace is not None:
- users.append("system:serviceaccount:%s:%s" % (namespace, x['name']))
+ users.append(
+ "system:serviceaccount:%s:%s" % (namespace, x["name"])
+ )
return users, groups
candidates = []
changed = False
for item in result:
- subjects = item.get('subjects', [])
- retainedSubjects = [x for x in subjects if x['kind'] == ref_kind and x['name'] in ref_names]
+ subjects = item.get("subjects", [])
+ retainedSubjects = [
+ x for x in subjects if x["kind"] == ref_kind and x["name"] in ref_names
+ ]
if len(subjects) != len(retainedSubjects):
updated_binding = item
- updated_binding['subjects'] = retainedSubjects
- binding_namespace = item['metadata'].get('namespace', None)
- updated_binding['userNames'], updated_binding['groupNames'] = _update_user_group(binding_namespace, retainedSubjects)
- candidates.append(binding_namespace + "/" + item['metadata']['name'] if binding_namespace else item['metadata']['name'])
+ updated_binding["subjects"] = retainedSubjects
+ binding_namespace = item["metadata"].get("namespace", None)
+ (
+ updated_binding["userNames"],
+ updated_binding["groupNames"],
+ ) = _update_user_group(binding_namespace, retainedSubjects)
+ candidates.append(
+ binding_namespace + "/" + item["metadata"]["name"]
+ if binding_namespace
+ else item["metadata"]["name"]
+ )
changed = True
if not self.check_mode:
try:
@@ -112,20 +136,25 @@ class OpenShiftAdmPruneAuth(AnsibleOpenshiftModule):
return candidates, changed
def update_security_context(self, ref_names, key):
- params = {'kind': 'SecurityContextConstraints', 'api_version': 'security.openshift.io/v1'}
+ params = {
+ "kind": "SecurityContextConstraints",
+ "api_version": "security.openshift.io/v1",
+ }
sccs = self.kubernetes_facts(**params)
- if not sccs['api_found']:
- self.fail_json(msg=sccs['msg'])
- sccs = sccs.get('resources')
+ if not sccs["api_found"]:
+ self.fail_json(msg=sccs["msg"])
+ sccs = sccs.get("resources")
candidates = []
changed = False
- resource = self.find_resource(kind="SecurityContextConstraints", api_version="security.openshift.io/v1")
+ resource = self.find_resource(
+ kind="SecurityContextConstraints", api_version="security.openshift.io/v1"
+ )
for item in sccs:
subjects = item.get(key, [])
retainedSubjects = [x for x in subjects if x not in ref_names]
if len(subjects) != len(retainedSubjects):
- candidates.append(item['metadata']['name'])
+ candidates.append(item["metadata"]["name"])
changed = True
if not self.check_mode:
upd_sec_ctx = item
@@ -138,94 +167,116 @@ class OpenShiftAdmPruneAuth(AnsibleOpenshiftModule):
return candidates, changed
def auth_prune_roles(self):
- params = {'kind': 'Role', 'api_version': 'rbac.authorization.k8s.io/v1', 'namespace': self.params.get('namespace')}
- for attr in ('name', 'label_selectors'):
+ params = {
+ "kind": "Role",
+ "api_version": "rbac.authorization.k8s.io/v1",
+ "namespace": self.params.get("namespace"),
+ }
+ for attr in ("name", "label_selectors"):
if self.params.get(attr):
params[attr] = self.params.get(attr)
result = self.kubernetes_facts(**params)
- if not result['api_found']:
- self.fail_json(msg=result['msg'])
+ if not result["api_found"]:
+ self.fail_json(msg=result["msg"])
- roles = result.get('resources')
+ roles = result.get("resources")
if len(roles) == 0:
- self.exit_json(changed=False, msg="No candidate rolebinding to prune from namespace %s." % self.params.get('namespace'))
+ self.exit_json(
+ changed=False,
+ msg="No candidate rolebinding to prune from namespace %s."
+ % self.params.get("namespace"),
+ )
- ref_roles = [(x['metadata']['namespace'], x['metadata']['name']) for x in roles]
- candidates = self.prune_resource_binding(kind="RoleBinding",
- api_version="rbac.authorization.k8s.io/v1",
- ref_kind="Role",
- ref_namespace_names=ref_roles,
- propagation_policy='Foreground')
+ ref_roles = [(x["metadata"]["namespace"], x["metadata"]["name"]) for x in roles]
+ candidates = self.prune_resource_binding(
+ kind="RoleBinding",
+ api_version="rbac.authorization.k8s.io/v1",
+ ref_kind="Role",
+ ref_namespace_names=ref_roles,
+ propagation_policy="Foreground",
+ )
if len(candidates) == 0:
self.exit_json(changed=False, role_binding=candidates)
self.exit_json(changed=True, role_binding=candidates)
def auth_prune_clusterroles(self):
- params = {'kind': 'ClusterRole', 'api_version': 'rbac.authorization.k8s.io/v1'}
- for attr in ('name', 'label_selectors'):
+ params = {"kind": "ClusterRole", "api_version": "rbac.authorization.k8s.io/v1"}
+ for attr in ("name", "label_selectors"):
if self.params.get(attr):
params[attr] = self.params.get(attr)
result = self.kubernetes_facts(**params)
- if not result['api_found']:
- self.fail_json(msg=result['msg'])
+ if not result["api_found"]:
+ self.fail_json(msg=result["msg"])
- clusterroles = result.get('resources')
+ clusterroles = result.get("resources")
if len(clusterroles) == 0:
- self.exit_json(changed=False, msg="No clusterroles found matching input criteria.")
+ self.exit_json(
+ changed=False, msg="No clusterroles found matching input criteria."
+ )
- ref_clusterroles = [(None, x['metadata']['name']) for x in clusterroles]
+ ref_clusterroles = [(None, x["metadata"]["name"]) for x in clusterroles]
# Prune ClusterRoleBinding
- candidates_cluster_binding = self.prune_resource_binding(kind="ClusterRoleBinding",
- api_version="rbac.authorization.k8s.io/v1",
- ref_kind=None,
- ref_namespace_names=ref_clusterroles)
+ candidates_cluster_binding = self.prune_resource_binding(
+ kind="ClusterRoleBinding",
+ api_version="rbac.authorization.k8s.io/v1",
+ ref_kind=None,
+ ref_namespace_names=ref_clusterroles,
+ )
# Prune Role Binding
- candidates_namespaced_binding = self.prune_resource_binding(kind="RoleBinding",
- api_version="rbac.authorization.k8s.io/v1",
- ref_kind='ClusterRole',
- ref_namespace_names=ref_clusterroles)
+ candidates_namespaced_binding = self.prune_resource_binding(
+ kind="RoleBinding",
+ api_version="rbac.authorization.k8s.io/v1",
+ ref_kind="ClusterRole",
+ ref_namespace_names=ref_clusterroles,
+ )
- self.exit_json(changed=True,
- cluster_role_binding=candidates_cluster_binding,
- role_binding=candidates_namespaced_binding)
+ self.exit_json(
+ changed=True,
+ cluster_role_binding=candidates_cluster_binding,
+ role_binding=candidates_namespaced_binding,
+ )
def list_groups(self, params=None):
- options = {'kind': 'Group', 'api_version': 'user.openshift.io/v1'}
+ options = {"kind": "Group", "api_version": "user.openshift.io/v1"}
if params:
- for attr in ('name', 'label_selectors'):
+ for attr in ("name", "label_selectors"):
if params.get(attr):
options[attr] = params.get(attr)
return self.kubernetes_facts(**options)
def auth_prune_users(self):
- params = {'kind': 'User', 'api_version': 'user.openshift.io/v1'}
- for attr in ('name', 'label_selectors'):
+ params = {"kind": "User", "api_version": "user.openshift.io/v1"}
+ for attr in ("name", "label_selectors"):
if self.params.get(attr):
params[attr] = self.params.get(attr)
users = self.kubernetes_facts(**params)
if len(users) == 0:
- self.exit_json(changed=False, msg="No resource type 'User' found matching input criteria.")
+ self.exit_json(
+ changed=False,
+ msg="No resource type 'User' found matching input criteria.",
+ )
- names = [x['metadata']['name'] for x in users]
+ names = [x["metadata"]["name"] for x in users]
changed = False
# Remove the user role binding
- rolebinding, changed_role = self.update_resource_binding(ref_kind="User",
- ref_names=names,
- namespaced=True)
+ rolebinding, changed_role = self.update_resource_binding(
+ ref_kind="User", ref_names=names, namespaced=True
+ )
changed = changed or changed_role
# Remove the user cluster role binding
- clusterrolesbinding, changed_cr = self.update_resource_binding(ref_kind="User",
- ref_names=names)
+ clusterrolesbinding, changed_cr = self.update_resource_binding(
+ ref_kind="User", ref_names=names
+ )
changed = changed or changed_cr
# Remove the user from security context constraints
- sccs, changed_sccs = self.update_security_context(names, 'users')
+ sccs, changed_sccs = self.update_security_context(names, "users")
changed = changed or changed_sccs
# Remove the user from groups
@@ -233,14 +284,14 @@ class OpenShiftAdmPruneAuth(AnsibleOpenshiftModule):
deleted_groups = []
resource = self.find_resource(kind="Group", api_version="user.openshift.io/v1")
for grp in groups:
- subjects = grp.get('users', [])
+ subjects = grp.get("users", [])
retainedSubjects = [x for x in subjects if x not in names]
if len(subjects) != len(retainedSubjects):
- deleted_groups.append(grp['metadata']['name'])
+ deleted_groups.append(grp["metadata"]["name"])
changed = True
if not self.check_mode:
upd_group = grp
- upd_group.update({'users': retainedSubjects})
+ upd_group.update({"users": retainedSubjects})
try:
resource.apply(upd_group, namespace=None)
except DynamicApiError as exc:
@@ -248,62 +299,82 @@ class OpenShiftAdmPruneAuth(AnsibleOpenshiftModule):
self.fail_json(msg=msg)
# Remove the user's OAuthClientAuthorizations
- oauth = self.kubernetes_facts(kind='OAuthClientAuthorization', api_version='oauth.openshift.io/v1')
+ oauth = self.kubernetes_facts(
+ kind="OAuthClientAuthorization", api_version="oauth.openshift.io/v1"
+ )
deleted_auths = []
- resource = self.find_resource(kind="OAuthClientAuthorization", api_version="oauth.openshift.io/v1")
+ resource = self.find_resource(
+ kind="OAuthClientAuthorization", api_version="oauth.openshift.io/v1"
+ )
for authorization in oauth:
- if authorization.get('userName', None) in names:
- auth_name = authorization['metadata']['name']
+ if authorization.get("userName", None) in names:
+ auth_name = authorization["metadata"]["name"]
deleted_auths.append(auth_name)
changed = True
if not self.check_mode:
try:
- resource.delete(name=auth_name, namespace=None, body=client.V1DeleteOptions())
+ resource.delete(
+ name=auth_name,
+ namespace=None,
+ body=client.V1DeleteOptions(),
+ )
except DynamicApiError as exc:
- msg = "Failed to delete OAuthClientAuthorization {name} due to: {msg}".format(name=auth_name, msg=exc.body)
+ msg = "Failed to delete OAuthClientAuthorization {name} due to: {msg}".format(
+ name=auth_name, msg=exc.body
+ )
self.fail_json(msg=msg)
except Exception as e:
- msg = "Failed to delete OAuthClientAuthorization {name} due to: {msg}".format(name=auth_name, msg=to_native(e))
+ msg = "Failed to delete OAuthClientAuthorization {name} due to: {msg}".format(
+ name=auth_name, msg=to_native(e)
+ )
self.fail_json(msg=msg)
- self.exit_json(changed=changed,
- cluster_role_binding=clusterrolesbinding,
- role_binding=rolebinding,
- security_context_constraints=sccs,
- authorization=deleted_auths,
- group=deleted_groups)
+ self.exit_json(
+ changed=changed,
+ cluster_role_binding=clusterrolesbinding,
+ role_binding=rolebinding,
+ security_context_constraints=sccs,
+ authorization=deleted_auths,
+ group=deleted_groups,
+ )
def auth_prune_groups(self):
groups = self.list_groups(params=self.params)
if len(groups) == 0:
- self.exit_json(changed=False, result="No resource type 'Group' found matching input criteria.")
+ self.exit_json(
+ changed=False,
+ result="No resource type 'Group' found matching input criteria.",
+ )
- names = [x['metadata']['name'] for x in groups]
+ names = [x["metadata"]["name"] for x in groups]
changed = False
# Remove the groups role binding
- rolebinding, changed_role = self.update_resource_binding(ref_kind="Group",
- ref_names=names,
- namespaced=True)
+ rolebinding, changed_role = self.update_resource_binding(
+ ref_kind="Group", ref_names=names, namespaced=True
+ )
changed = changed or changed_role
# Remove the groups cluster role binding
- clusterrolesbinding, changed_cr = self.update_resource_binding(ref_kind="Group",
- ref_names=names)
+ clusterrolesbinding, changed_cr = self.update_resource_binding(
+ ref_kind="Group", ref_names=names
+ )
changed = changed or changed_cr
# Remove the groups security context constraints
- sccs, changed_sccs = self.update_security_context(names, 'groups')
+ sccs, changed_sccs = self.update_security_context(names, "groups")
changed = changed or changed_sccs
- self.exit_json(changed=changed,
- cluster_role_binding=clusterrolesbinding,
- role_binding=rolebinding,
- security_context_constraints=sccs)
+ self.exit_json(
+ changed=changed,
+ cluster_role_binding=clusterrolesbinding,
+ role_binding=rolebinding,
+ security_context_constraints=sccs,
+ )
def execute_module(self):
auth_prune = {
- 'roles': self.auth_prune_roles,
- 'clusterroles': self.auth_prune_clusterroles,
- 'users': self.auth_prune_users,
- 'groups': self.auth_prune_groups,
+ "roles": self.auth_prune_roles,
+ "clusterroles": self.auth_prune_clusterroles,
+ "users": self.auth_prune_users,
+ "groups": self.auth_prune_groups,
}
- auth_prune[self.params.get('resource')]()
+ auth_prune[self.params.get("resource")]()
diff --git a/plugins/module_utils/openshift_adm_prune_deployments.py b/plugins/module_utils/openshift_adm_prune_deployments.py
index 418922d..315de4b 100644
--- a/plugins/module_utils/openshift_adm_prune_deployments.py
+++ b/plugins/module_utils/openshift_adm_prune_deployments.py
@@ -1,14 +1,16 @@
#!/usr/bin/env python
-from __future__ import (absolute_import, division, print_function)
+from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
from datetime import datetime, timezone
-import traceback
from ansible.module_utils._text import to_native
-from ansible_collections.community.okd.plugins.module_utils.openshift_common import AnsibleOpenshiftModule
+from ansible_collections.community.okd.plugins.module_utils.openshift_common import (
+ AnsibleOpenshiftModule,
+)
try:
from kubernetes import client
@@ -23,7 +25,9 @@ def get_deploymentconfig_for_replicationcontroller(replica_controller):
# This is set on replication controller pod template by deployer controller.
DeploymentConfigAnnotation = "openshift.io/deployment-config.name"
try:
- deploymentconfig_name = replica_controller['metadata']['annotations'].get(DeploymentConfigAnnotation)
+ deploymentconfig_name = replica_controller["metadata"]["annotations"].get(
+ DeploymentConfigAnnotation
+ )
if deploymentconfig_name is None or deploymentconfig_name == "":
return None
return deploymentconfig_name
@@ -32,7 +36,6 @@ def get_deploymentconfig_for_replicationcontroller(replica_controller):
class OpenShiftAdmPruneDeployment(AnsibleOpenshiftModule):
-
def __init__(self, **kwargs):
super(OpenShiftAdmPruneDeployment, self).__init__(**kwargs)
@@ -41,27 +44,33 @@ class OpenShiftAdmPruneDeployment(AnsibleOpenshiftModule):
return get_deploymentconfig_for_replicationcontroller(obj) is not None
def _zeroReplicaSize(obj):
- return obj['spec']['replicas'] == 0 and obj['status']['replicas'] == 0
+ return obj["spec"]["replicas"] == 0 and obj["status"]["replicas"] == 0
def _complete_failed(obj):
DeploymentStatusAnnotation = "openshift.io/deployment.phase"
try:
# validate that replication controller status is either 'Complete' or 'Failed'
- deployment_phase = obj['metadata']['annotations'].get(DeploymentStatusAnnotation)
- return deployment_phase in ('Failed', 'Complete')
+ deployment_phase = obj["metadata"]["annotations"].get(
+ DeploymentStatusAnnotation
+ )
+ return deployment_phase in ("Failed", "Complete")
except Exception:
return False
def _younger(obj):
- creation_timestamp = datetime.strptime(obj['metadata']['creationTimestamp'], '%Y-%m-%dT%H:%M:%SZ')
+ creation_timestamp = datetime.strptime(
+ obj["metadata"]["creationTimestamp"], "%Y-%m-%dT%H:%M:%SZ"
+ )
now = datetime.now(timezone.utc).replace(tzinfo=None)
age = (now - creation_timestamp).seconds / 60
- return age > self.params['keep_younger_than']
+ return age > self.params["keep_younger_than"]
def _orphan(obj):
try:
# verify if the deploymentconfig associated to the replication controller is still existing
- deploymentconfig_name = get_deploymentconfig_for_replicationcontroller(obj)
+ deploymentconfig_name = get_deploymentconfig_for_replicationcontroller(
+ obj
+ )
params = dict(
kind="DeploymentConfig",
api_version="apps.openshift.io/v1",
@@ -69,14 +78,14 @@ class OpenShiftAdmPruneDeployment(AnsibleOpenshiftModule):
namespace=obj["metadata"]["name"],
)
exists = self.kubernetes_facts(**params)
- return not (exists.get['api_found'] and len(exists['resources']) > 0)
+ return not (exists.get["api_found"] and len(exists["resources"]) > 0)
except Exception:
return False
predicates = [_deployment, _zeroReplicaSize, _complete_failed]
- if self.params['orphans']:
+ if self.params["orphans"]:
predicates.append(_orphan)
- if self.params['keep_younger_than']:
+ if self.params["keep_younger_than"]:
predicates.append(_younger)
results = replicacontrollers.copy()
@@ -86,8 +95,8 @@ class OpenShiftAdmPruneDeployment(AnsibleOpenshiftModule):
def execute_module(self):
# list replicationcontroller candidate for pruning
- kind = 'ReplicationController'
- api_version = 'v1'
+ kind = "ReplicationController"
+ api_version = "v1"
resource = self.find_resource(kind=kind, api_version=api_version, fail=True)
# Get ReplicationController
@@ -103,7 +112,7 @@ class OpenShiftAdmPruneDeployment(AnsibleOpenshiftModule):
self.exit_json(changed=False, replication_controllers=[])
changed = True
- delete_options = client.V1DeleteOptions(propagation_policy='Background')
+ delete_options = client.V1DeleteOptions(propagation_policy="Background")
replication_controllers = []
for replica in candidates:
try:
@@ -111,12 +120,18 @@ class OpenShiftAdmPruneDeployment(AnsibleOpenshiftModule):
if not self.check_mode:
name = replica["metadata"]["name"]
namespace = replica["metadata"]["namespace"]
- result = resource.delete(name=name, namespace=namespace, body=delete_options).to_dict()
+ result = resource.delete(
+ name=name, namespace=namespace, body=delete_options
+ ).to_dict()
replication_controllers.append(result)
except DynamicApiError as exc:
- msg = "Failed to delete ReplicationController {namespace}/{name} due to: {msg}".format(namespace=namespace, name=name, msg=exc.body)
+ msg = "Failed to delete ReplicationController {namespace}/{name} due to: {msg}".format(
+ namespace=namespace, name=name, msg=exc.body
+ )
self.fail_json(msg=msg)
except Exception as e:
- msg = "Failed to delete ReplicationController {namespace}/{name} due to: {msg}".format(namespace=namespace, name=name, msg=to_native(e))
+ msg = "Failed to delete ReplicationController {namespace}/{name} due to: {msg}".format(
+ namespace=namespace, name=name, msg=to_native(e)
+ )
self.fail_json(msg=msg)
self.exit_json(changed=changed, replication_controllers=replication_controllers)
diff --git a/plugins/module_utils/openshift_adm_prune_images.py b/plugins/module_utils/openshift_adm_prune_images.py
index 442cf90..768c359 100644
--- a/plugins/module_utils/openshift_adm_prune_images.py
+++ b/plugins/module_utils/openshift_adm_prune_images.py
@@ -1,17 +1,19 @@
#!/usr/bin/env python
-from __future__ import (absolute_import, division, print_function)
+from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
from datetime import datetime, timezone, timedelta
-import traceback
import copy
from ansible.module_utils._text import to_native
from ansible.module_utils.parsing.convert_bool import boolean
from ansible.module_utils.six import iteritems
-from ansible_collections.community.okd.plugins.module_utils.openshift_common import AnsibleOpenshiftModule
+from ansible_collections.community.okd.plugins.module_utils.openshift_common import (
+ AnsibleOpenshiftModule,
+)
from ansible_collections.community.okd.plugins.module_utils.openshift_images_common import (
OpenShiftAnalyzeImageStream,
@@ -30,7 +32,7 @@ try:
from kubernetes.dynamic.exceptions import (
DynamicApiError,
NotFoundError,
- ApiException
+ ApiException,
)
except ImportError:
pass
@@ -67,18 +69,20 @@ def determine_host_registry(module, images, image_streams):
managed_images = list(filter(_f_managed_images, images))
# Be sure to pick up the newest managed image which should have an up to date information
- sorted_images = sorted(managed_images,
- key=lambda x: x["metadata"]["creationTimestamp"],
- reverse=True)
+ sorted_images = sorted(
+ managed_images, key=lambda x: x["metadata"]["creationTimestamp"], reverse=True
+ )
docker_image_ref = ""
if len(sorted_images) > 0:
docker_image_ref = sorted_images[0].get("dockerImageReference", "")
else:
# 2nd try to get the pull spec from any image stream
# Sorting by creation timestamp may not get us up to date info. Modification time would be much
- sorted_image_streams = sorted(image_streams,
- key=lambda x: x["metadata"]["creationTimestamp"],
- reverse=True)
+ sorted_image_streams = sorted(
+ image_streams,
+ key=lambda x: x["metadata"]["creationTimestamp"],
+ reverse=True,
+ )
for i_stream in sorted_image_streams:
docker_image_ref = i_stream["status"].get("dockerImageRepository", "")
if len(docker_image_ref) > 0:
@@ -88,7 +92,7 @@ def determine_host_registry(module, images, image_streams):
module.exit_json(changed=False, result="no managed image found")
result, error = parse_docker_image_ref(docker_image_ref, module)
- return result['hostname']
+ return result["hostname"]
class OpenShiftAdmPruneImages(AnsibleOpenshiftModule):
@@ -97,7 +101,7 @@ class OpenShiftAdmPruneImages(AnsibleOpenshiftModule):
self.max_creation_timestamp = self.get_max_creation_timestamp()
self._rest_client = None
- self.registryhost = self.params.get('registry_url')
+ self.registryhost = self.params.get("registry_url")
self.changed = False
def list_objects(self):
@@ -107,9 +111,9 @@ class OpenShiftAdmPruneImages(AnsibleOpenshiftModule):
if self.params.get("namespace") and kind.lower() == "imagestream":
namespace = self.params.get("namespace")
try:
- result[kind] = self.kubernetes_facts(kind=kind,
- api_version=version,
- namespace=namespace).get('resources')
+ result[kind] = self.kubernetes_facts(
+ kind=kind, api_version=version, namespace=namespace
+ ).get("resources")
except DynamicApiError as e:
self.fail_json(
msg="An error occurred while trying to list objects.",
@@ -119,7 +123,7 @@ class OpenShiftAdmPruneImages(AnsibleOpenshiftModule):
except Exception as e:
self.fail_json(
msg="An error occurred while trying to list objects.",
- error=to_native(e)
+ error=to_native(e),
)
return result
@@ -134,8 +138,8 @@ class OpenShiftAdmPruneImages(AnsibleOpenshiftModule):
def rest_client(self):
if not self._rest_client:
configuration = copy.deepcopy(self.client.configuration)
- validate_certs = self.params.get('registry_validate_certs')
- ssl_ca_cert = self.params.get('registry_ca_cert')
+ validate_certs = self.params.get("registry_validate_certs")
+ ssl_ca_cert = self.params.get("registry_ca_cert")
if validate_certs is not None:
configuration.verify_ssl = validate_certs
if ssl_ca_cert is not None:
@@ -146,7 +150,9 @@ class OpenShiftAdmPruneImages(AnsibleOpenshiftModule):
def delete_from_registry(self, url):
try:
- response = self.rest_client.DELETE(url=url, headers=self.client.configuration.api_key)
+ response = self.rest_client.DELETE(
+ url=url, headers=self.client.configuration.api_key
+ )
if response.status == 404:
# Unable to delete layer
return None
@@ -156,8 +162,9 @@ class OpenShiftAdmPruneImages(AnsibleOpenshiftModule):
if response.status != 202 and response.status != 204:
self.fail_json(
msg="Delete URL {0}: Unexpected status code in response: {1}".format(
- response.status, url),
- reason=response.reason
+ response.status, url
+ ),
+ reason=response.reason,
)
return None
except ApiException as e:
@@ -204,9 +211,7 @@ class OpenShiftAdmPruneImages(AnsibleOpenshiftModule):
result = self.request(
"PUT",
"/apis/{api_version}/namespaces/{namespace}/imagestreams/{name}/status".format(
- api_version=api_version,
- namespace=namespace,
- name=name
+ api_version=api_version, namespace=namespace, name=name
),
body=definition,
content_type="application/json",
@@ -237,11 +242,10 @@ class OpenShiftAdmPruneImages(AnsibleOpenshiftModule):
pass
except DynamicApiError as exc:
self.fail_json(
- msg="Failed to delete object %s/%s due to: %s" % (
- kind, name, exc.body
- ),
+ msg="Failed to delete object %s/%s due to: %s"
+ % (kind, name, exc.body),
reason=exc.reason,
- status=exc.status
+ status=exc.status,
)
else:
existing = resource.get(name=name)
@@ -285,9 +289,11 @@ class OpenShiftAdmPruneImages(AnsibleOpenshiftModule):
continue
if idx == 0:
- istag = "%s/%s:%s" % (stream_namespace,
- stream_name,
- tag_event_list["tag"])
+ istag = "%s/%s:%s" % (
+ stream_namespace,
+ stream_name,
+ tag_event_list["tag"],
+ )
if istag in self.used_tags:
# keeping because tag is used
filtered_items.append(item)
@@ -302,20 +308,20 @@ class OpenShiftAdmPruneImages(AnsibleOpenshiftModule):
image = self.image_mapping[item["image"]]
# check prune over limit size
- if prune_over_size_limit and not self.exceeds_limits(stream_namespace, image):
+ if prune_over_size_limit and not self.exceeds_limits(
+ stream_namespace, image
+ ):
filtered_items.append(item)
continue
- image_ref = "%s/%s@%s" % (stream_namespace,
- stream_name,
- item["image"])
+ image_ref = "%s/%s@%s" % (stream_namespace, stream_name, item["image"])
if image_ref in self.used_images:
# keeping because tag is used
filtered_items.append(item)
continue
images_to_delete.append(item["image"])
- if self.params.get('prune_registry'):
+ if self.params.get("prune_registry"):
manifests_to_delete.append(image["metadata"]["name"])
path = stream_namespace + "/" + stream_name
image_blobs, err = get_image_blobs(image)
@@ -325,21 +331,25 @@ class OpenShiftAdmPruneImages(AnsibleOpenshiftModule):
return filtered_items, manifests_to_delete, images_to_delete
def prune_image_streams(self, stream):
- name = stream['metadata']['namespace'] + "/" + stream['metadata']['name']
+ name = stream["metadata"]["namespace"] + "/" + stream["metadata"]["name"]
if is_too_young_object(stream, self.max_creation_timestamp):
# keeping all images because of image stream too young
return None, []
- facts = self.kubernetes_facts(kind="ImageStream",
- api_version=ApiConfiguration.get("ImageStream"),
- name=stream["metadata"]["name"],
- namespace=stream["metadata"]["namespace"])
- image_stream = facts.get('resources')
+ facts = self.kubernetes_facts(
+ kind="ImageStream",
+ api_version=ApiConfiguration.get("ImageStream"),
+ name=stream["metadata"]["name"],
+ namespace=stream["metadata"]["namespace"],
+ )
+ image_stream = facts.get("resources")
if len(image_stream) != 1:
# skipping because it does not exist anymore
return None, []
stream = image_stream[0]
namespace = self.params.get("namespace")
- stream_to_update = not namespace or (stream["metadata"]["namespace"] == namespace)
+ stream_to_update = not namespace or (
+ stream["metadata"]["namespace"] == namespace
+ )
manifests_to_delete, images_to_delete = [], []
deleted_items = False
@@ -351,9 +361,9 @@ class OpenShiftAdmPruneImages(AnsibleOpenshiftModule):
(
filtered_tag_event,
tag_manifests_to_delete,
- tag_images_to_delete
+ tag_images_to_delete,
) = self.prune_image_stream_tag(stream, tag_event_list)
- stream['status']['tags'][idx]['items'] = filtered_tag_event
+ stream["status"]["tags"][idx]["items"] = filtered_tag_event
manifests_to_delete += tag_manifests_to_delete
images_to_delete += tag_images_to_delete
deleted_items = deleted_items or (len(tag_images_to_delete) > 0)
@@ -361,11 +371,11 @@ class OpenShiftAdmPruneImages(AnsibleOpenshiftModule):
# Deleting tags without items
tags = []
for tag in stream["status"].get("tags", []):
- if tag['items'] is None or len(tag['items']) == 0:
+ if tag["items"] is None or len(tag["items"]) == 0:
continue
tags.append(tag)
- stream['status']['tags'] = tags
+ stream["status"]["tags"] = tags
result = None
# Update ImageStream
if stream_to_update:
@@ -402,19 +412,23 @@ class OpenShiftAdmPruneImages(AnsibleOpenshiftModule):
def execute_module(self):
resources = self.list_objects()
- if not self.check_mode and self.params.get('prune_registry'):
+ if not self.check_mode and self.params.get("prune_registry"):
if not self.registryhost:
- self.registryhost = determine_host_registry(self.module, resources['Image'], resources['ImageStream'])
+ self.registryhost = determine_host_registry(
+ self.module, resources["Image"], resources["ImageStream"]
+ )
# validate that host has a scheme
if "://" not in self.registryhost:
self.registryhost = "https://" + self.registryhost
# Analyze Image Streams
analyze_ref = OpenShiftAnalyzeImageStream(
- ignore_invalid_refs=self.params.get('ignore_invalid_refs'),
+ ignore_invalid_refs=self.params.get("ignore_invalid_refs"),
max_creation_timestamp=self.max_creation_timestamp,
- module=self.module
+ module=self.module,
+ )
+ self.used_tags, self.used_images, error = analyze_ref.analyze_image_stream(
+ resources
)
- self.used_tags, self.used_images, error = analyze_ref.analyze_image_stream(resources)
if error:
self.fail_json(msg=error)
@@ -435,16 +449,20 @@ class OpenShiftAdmPruneImages(AnsibleOpenshiftModule):
updated_image_streams = []
deleted_tags_images = []
updated_is_mapping = {}
- for stream in resources['ImageStream']:
+ for stream in resources["ImageStream"]:
result, images_to_delete = self.prune_image_streams(stream)
if result:
- updated_is_mapping[result["metadata"]["namespace"] + "/" + result["metadata"]["name"]] = result
+ updated_is_mapping[
+ result["metadata"]["namespace"] + "/" + result["metadata"]["name"]
+ ] = result
updated_image_streams.append(result)
deleted_tags_images += images_to_delete
# Create a list with images referenced on image stream
self.referenced_images = []
- for item in self.kubernetes_facts(kind="ImageStream", api_version="image.openshift.io/v1")["resources"]:
+ for item in self.kubernetes_facts(
+ kind="ImageStream", api_version="image.openshift.io/v1"
+ )["resources"]:
name = "%s/%s" % (item["metadata"]["namespace"], item["metadata"]["name"])
if name in updated_is_mapping:
item = updated_is_mapping[name]
@@ -453,7 +471,7 @@ class OpenShiftAdmPruneImages(AnsibleOpenshiftModule):
# Stage 2: delete images
images = []
- images_to_delete = [x["metadata"]["name"] for x in resources['Image']]
+ images_to_delete = [x["metadata"]["name"] for x in resources["Image"]]
if self.params.get("namespace") is not None:
# When namespace is defined, prune only images that were referenced by ImageStream
# from the corresponding namespace
diff --git a/plugins/module_utils/openshift_builds.py b/plugins/module_utils/openshift_builds.py
index 02e60fd..51ebfc2 100644
--- a/plugins/module_utils/openshift_builds.py
+++ b/plugins/module_utils/openshift_builds.py
@@ -1,15 +1,17 @@
#!/usr/bin/env python
-from __future__ import (absolute_import, division, print_function)
+from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
from datetime import datetime, timezone, timedelta
-import traceback
import time
from ansible.module_utils._text import to_native
-from ansible_collections.community.okd.plugins.module_utils.openshift_common import AnsibleOpenshiftModule
+from ansible_collections.community.okd.plugins.module_utils.openshift_common import (
+ AnsibleOpenshiftModule,
+)
try:
from kubernetes.dynamic.exceptions import DynamicApiError
@@ -36,8 +38,7 @@ class OpenShiftBuilds(AnsibleOpenshiftModule):
result = self.request(
method="POST",
path="/apis/build.openshift.io/v1/namespaces/{namespace}/builds/{name}/clone".format(
- namespace=namespace,
- name=name
+ namespace=namespace, name=name
),
body=request,
content_type="application/json",
@@ -47,7 +48,11 @@ class OpenShiftBuilds(AnsibleOpenshiftModule):
msg = "Failed to clone Build %s/%s due to: %s" % (namespace, name, exc.body)
self.fail_json(msg=msg, status=exc.status, reason=exc.reason)
except Exception as e:
- msg = "Failed to clone Build %s/%s due to: %s" % (namespace, name, to_native(e))
+ msg = "Failed to clone Build %s/%s due to: %s" % (
+ namespace,
+ name,
+ to_native(e),
+ )
self.fail_json(msg=msg, error=to_native(e), exception=e)
def instantiate_build_config(self, name, namespace, request):
@@ -55,22 +60,28 @@ class OpenShiftBuilds(AnsibleOpenshiftModule):
result = self.request(
method="POST",
path="/apis/build.openshift.io/v1/namespaces/{namespace}/buildconfigs/{name}/instantiate".format(
- namespace=namespace,
- name=name
+ namespace=namespace, name=name
),
body=request,
content_type="application/json",
)
return result.to_dict()
except DynamicApiError as exc:
- msg = "Failed to instantiate BuildConfig %s/%s due to: %s" % (namespace, name, exc.body)
+ msg = "Failed to instantiate BuildConfig %s/%s due to: %s" % (
+ namespace,
+ name,
+ exc.body,
+ )
self.fail_json(msg=msg, status=exc.status, reason=exc.reason)
except Exception as e:
- msg = "Failed to instantiate BuildConfig %s/%s due to: %s" % (namespace, name, to_native(e))
+ msg = "Failed to instantiate BuildConfig %s/%s due to: %s" % (
+ namespace,
+ name,
+ to_native(e),
+ )
self.fail_json(msg=msg, error=to_native(e), exception=e)
def start_build(self):
-
result = None
name = self.params.get("build_config_name")
if not name:
@@ -79,32 +90,20 @@ class OpenShiftBuilds(AnsibleOpenshiftModule):
build_request = {
"kind": "BuildRequest",
"apiVersion": "build.openshift.io/v1",
- "metadata": {
- "name": name
- },
- "triggeredBy": [
- {"message": "Manually triggered"}
- ],
+ "metadata": {"name": name},
+ "triggeredBy": [{"message": "Manually triggered"}],
}
# Overrides incremental
incremental = self.params.get("incremental")
if incremental is not None:
build_request.update(
- {
- "sourceStrategyOptions": {
- "incremental": incremental
- }
- }
+ {"sourceStrategyOptions": {"incremental": incremental}}
)
# Environment variable
if self.params.get("env_vars"):
- build_request.update(
- {
- "env": self.params.get("env_vars")
- }
- )
+ build_request.update({"env": self.params.get("env_vars")})
# Docker strategy option
if self.params.get("build_args"):
@@ -121,22 +120,14 @@ class OpenShiftBuilds(AnsibleOpenshiftModule):
if no_cache is not None:
build_request.update(
{
- "dockerStrategyOptions": {
- "noCache": no_cache
- },
+ "dockerStrategyOptions": {"noCache": no_cache},
}
)
# commit
if self.params.get("commit"):
build_request.update(
- {
- "revision": {
- "git": {
- "commit": self.params.get("commit")
- }
- }
- }
+ {"revision": {"git": {"commit": self.params.get("commit")}}}
)
if self.params.get("build_config_name"):
@@ -144,7 +135,7 @@ class OpenShiftBuilds(AnsibleOpenshiftModule):
result = self.instantiate_build_config(
name=self.params.get("build_config_name"),
namespace=self.params.get("namespace"),
- request=build_request
+ request=build_request,
)
else:
@@ -152,7 +143,7 @@ class OpenShiftBuilds(AnsibleOpenshiftModule):
result = self.clone_build(
name=self.params.get("build_name"),
namespace=self.params.get("namespace"),
- request=build_request
+ request=build_request,
)
if result and self.params.get("wait"):
@@ -179,10 +170,11 @@ class OpenShiftBuilds(AnsibleOpenshiftModule):
break
elif last_status_phase in ("Cancelled", "Error", "Failed"):
self.fail_json(
- msg="Unexpected status for Build %s/%s: %s" % (
+ msg="Unexpected status for Build %s/%s: %s"
+ % (
result["metadata"]["name"],
result["metadata"]["namespace"],
- last_status_phase
+ last_status_phase,
)
)
time.sleep(wait_sleep)
@@ -190,8 +182,11 @@ class OpenShiftBuilds(AnsibleOpenshiftModule):
if last_status_phase != "Complete":
name = result["metadata"]["name"]
namespace = result["metadata"]["namespace"]
- msg = "Build %s/%s has not complete after %d second(s)," \
- "current status is %s" % (namespace, name, wait_timeout, last_status_phase)
+ msg = (
+ "Build %s/%s has not complete after %d second(s),"
+ "current status is %s"
+ % (namespace, name, wait_timeout, last_status_phase)
+ )
self.fail_json(msg=msg)
@@ -199,9 +194,8 @@ class OpenShiftBuilds(AnsibleOpenshiftModule):
self.exit_json(changed=True, builds=result)
def cancel_build(self, restart):
-
- kind = 'Build'
- api_version = 'build.openshift.io/v1'
+ kind = "Build"
+ api_version = "build.openshift.io/v1"
namespace = self.params.get("namespace")
phases = ["new", "pending", "running"]
@@ -215,16 +209,18 @@ class OpenShiftBuilds(AnsibleOpenshiftModule):
else:
build_config = self.params.get("build_config_name")
# list all builds from namespace
- params = dict(
- kind=kind,
- api_version=api_version,
- namespace=namespace
- )
+ params = dict(kind=kind, api_version=api_version, namespace=namespace)
resources = self.kubernetes_facts(**params).get("resources", [])
def _filter_builds(build):
- config = build["metadata"].get("labels", {}).get("openshift.io/build-config.name")
- return build_config is None or (build_config is not None and config in build_config)
+ config = (
+ build["metadata"]
+ .get("labels", {})
+ .get("openshift.io/build-config.name")
+ )
+ return build_config is None or (
+ build_config is not None and config in build_config
+ )
for item in list(filter(_filter_builds, resources)):
name = item["metadata"]["name"]
@@ -232,16 +228,15 @@ class OpenShiftBuilds(AnsibleOpenshiftModule):
names.append(name)
if len(names) == 0:
- self.exit_json(changed=False, msg="No Build found from namespace %s" % namespace)
+ self.exit_json(
+ changed=False, msg="No Build found from namespace %s" % namespace
+ )
warning = []
builds_to_cancel = []
for name in names:
params = dict(
- kind=kind,
- api_version=api_version,
- name=name,
- namespace=namespace
+ kind=kind, api_version=api_version, name=name, namespace=namespace
)
resource = self.kubernetes_facts(**params).get("resources", [])
@@ -256,7 +251,10 @@ class OpenShiftBuilds(AnsibleOpenshiftModule):
if phase in phases:
builds_to_cancel.append(resource)
else:
- warning.append("build %s/%s is not in expected phase, found %s" % (namespace, name, phase))
+ warning.append(
+ "build %s/%s is not in expected phase, found %s"
+ % (namespace, name, phase)
+ )
changed = False
result = []
@@ -278,9 +276,10 @@ class OpenShiftBuilds(AnsibleOpenshiftModule):
result.append(cancelled_build)
except DynamicApiError as exc:
self.fail_json(
- msg="Failed to cancel Build %s/%s due to: %s" % (namespace, name, exc),
+ msg="Failed to cancel Build %s/%s due to: %s"
+ % (namespace, name, exc),
reason=exc.reason,
- status=exc.status
+ status=exc.status,
)
except Exception as e:
self.fail_json(
@@ -294,10 +293,7 @@ class OpenShiftBuilds(AnsibleOpenshiftModule):
name = build["metadata"]["name"]
while (datetime.now() - start).seconds < wait_timeout:
params = dict(
- kind=kind,
- api_version=api_version,
- name=name,
- namespace=namespace
+ kind=kind, api_version=api_version, name=name, namespace=namespace
)
resource = self.kubernetes_facts(**params).get("resources", [])
if len(resource) == 0:
@@ -307,7 +303,11 @@ class OpenShiftBuilds(AnsibleOpenshiftModule):
if last_phase == "Cancelled":
return resource, None
time.sleep(wait_sleep)
- return None, "Build %s/%s is not cancelled as expected, current state is %s" % (namespace, name, last_phase)
+ return (
+ None,
+ "Build %s/%s is not cancelled as expected, current state is %s"
+ % (namespace, name, last_phase),
+ )
if result and self.params.get("wait"):
wait_timeout = self.params.get("wait_timeout")
@@ -341,8 +341,8 @@ class OpenShiftPruneBuilds(OpenShiftBuilds):
def execute_module(self):
# list replicationcontroller candidate for pruning
- kind = 'Build'
- api_version = 'build.openshift.io/v1'
+ kind = "Build"
+ api_version = "build.openshift.io/v1"
resource = self.find_resource(kind=kind, api_version=api_version, fail=True)
self.max_creation_timestamp = None
@@ -352,7 +352,12 @@ class OpenShiftPruneBuilds(OpenShiftBuilds):
self.max_creation_timestamp = now - timedelta(minutes=keep_younger_than)
def _prunable_build(build):
- return build["status"]["phase"] in ("Complete", "Failed", "Error", "Cancelled")
+ return build["status"]["phase"] in (
+ "Complete",
+ "Failed",
+ "Error",
+ "Cancelled",
+ )
def _orphan_build(build):
if not _prunable_build(build):
@@ -367,7 +372,9 @@ class OpenShiftPruneBuilds(OpenShiftBuilds):
def _younger_build(build):
if not self.max_creation_timestamp:
return False
- creation_timestamp = datetime.strptime(build['metadata']['creationTimestamp'], '%Y-%m-%dT%H:%M:%SZ')
+ creation_timestamp = datetime.strptime(
+ build["metadata"]["creationTimestamp"], "%Y-%m-%dT%H:%M:%SZ"
+ )
return creation_timestamp < self.max_creation_timestamp
predicates = [
@@ -401,9 +408,17 @@ class OpenShiftPruneBuilds(OpenShiftBuilds):
namespace = build["metadata"]["namespace"]
resource.delete(name=name, namespace=namespace, body={})
except DynamicApiError as exc:
- msg = "Failed to delete Build %s/%s due to: %s" % (namespace, name, exc.body)
+ msg = "Failed to delete Build %s/%s due to: %s" % (
+ namespace,
+ name,
+ exc.body,
+ )
self.fail_json(msg=msg, status=exc.status, reason=exc.reason)
except Exception as e:
- msg = "Failed to delete Build %s/%s due to: %s" % (namespace, name, to_native(e))
+ msg = "Failed to delete Build %s/%s due to: %s" % (
+ namespace,
+ name,
+ to_native(e),
+ )
self.fail_json(msg=msg, error=to_native(e), exception=e)
self.exit_json(changed=changed, builds=candidates)
diff --git a/plugins/module_utils/openshift_common.py b/plugins/module_utils/openshift_common.py
index a1318f9..b818b7a 100644
--- a/plugins/module_utils/openshift_common.py
+++ b/plugins/module_utils/openshift_common.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python
-from __future__ import (absolute_import, division, print_function)
+from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
import traceback
@@ -9,8 +10,12 @@ from abc import abstractmethod
from ansible.module_utils._text import to_native
try:
- from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import get_api_client
- from ansible_collections.kubernetes.core.plugins.module_utils.k8s.core import AnsibleK8SModule
+ from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
+ get_api_client,
+ )
+ from ansible_collections.kubernetes.core.plugins.module_utils.k8s.core import (
+ AnsibleK8SModule,
+ )
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.service import (
K8sService,
diff_objects,
@@ -24,7 +29,10 @@ try:
merge_params,
flatten_list_kind,
)
- from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import CoreException
+ from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import (
+ CoreException,
+ )
+
HAS_KUBERNETES_COLLECTION = True
k8s_collection_import_exception = None
K8S_COLLECTION_ERROR = None
@@ -35,7 +43,6 @@ except ImportError as e:
class AnsibleOpenshiftModule(AnsibleK8SModule):
-
def __init__(self, **kwargs):
super(AnsibleOpenshiftModule, self).__init__(**kwargs)
@@ -86,7 +93,6 @@ class AnsibleOpenshiftModule(AnsibleK8SModule):
return diff_objects(existing, new)
def run_module(self):
-
try:
self.execute_module()
except CoreException as e:
diff --git a/plugins/module_utils/openshift_docker_image.py b/plugins/module_utils/openshift_docker_image.py
index 27dbe6c..160c5b5 100644
--- a/plugins/module_utils/openshift_docker_image.py
+++ b/plugins/module_utils/openshift_docker_image.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python
-from __future__ import (absolute_import, division, print_function)
+from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
import re
@@ -23,62 +24,68 @@ def convert_storage_to_bytes(value):
def is_valid_digest(digest):
-
digest_algorithm_size = dict(
- sha256=64, sha384=96, sha512=128,
+ sha256=64,
+ sha384=96,
+ sha512=128,
)
- m = re.match(r'[a-zA-Z0-9-_+.]+:[a-fA-F0-9]+', digest)
+ m = re.match(r"[a-zA-Z0-9-_+.]+:[a-fA-F0-9]+", digest)
if not m:
return "Docker digest does not match expected format %s" % digest
- idx = digest.find(':')
+ idx = digest.find(":")
# case: "sha256:" with no hex.
if idx < 0 or idx == (len(digest) - 1):
return "Invalid docker digest %s, no hex value define" % digest
algorithm = digest[:idx]
if algorithm not in digest_algorithm_size:
- return "Unsupported digest algorithm value %s for digest %s" % (algorithm, digest)
+ return "Unsupported digest algorithm value %s for digest %s" % (
+ algorithm,
+ digest,
+ )
- hex_value = digest[idx + 1:]
+ hex_value = digest[idx + 1:] # fmt: skip
if len(hex_value) != digest_algorithm_size.get(algorithm):
return "Invalid length for digest hex expected %d found %d (digest is %s)" % (
- digest_algorithm_size.get(algorithm), len(hex_value), digest
+ digest_algorithm_size.get(algorithm),
+ len(hex_value),
+ digest,
)
def parse_docker_image_ref(image_ref, module=None):
"""
- Docker Grammar Reference
- Reference => name [ ":" tag ] [ "@" digest ]
- name => [hostname '/'] component ['/' component]*
- hostname => hostcomponent ['.' hostcomponent]* [':' port-number]
- hostcomponent => /([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])/
- port-number => /[0-9]+/
- component => alpha-numeric [separator alpha-numeric]*
- alpha-numeric => /[a-z0-9]+/
- separator => /[_.]|__|[-]*/
+ Docker Grammar Reference
+ Reference => name [ ":" tag ] [ "@" digest ]
+ name => [hostname '/'] component ['/' component]*
+ hostname => hostcomponent ['.' hostcomponent]* [':' port-number]
+ hostcomponent => /([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])/
+ port-number => /[0-9]+/
+ component => alpha-numeric [separator alpha-numeric]*
+ alpha-numeric => /[a-z0-9]+/
+ separator => /[_.]|__|[-]*/
"""
idx = image_ref.find("/")
def _contains_any(src, values):
return any(x in src for x in values)
- result = {
- "tag": None, "digest": None
- }
+ result = {"tag": None, "digest": None}
default_domain = "docker.io"
- if idx < 0 or (not _contains_any(image_ref[:idx], ":.") and image_ref[:idx] != "localhost"):
+ if idx < 0 or (
+ not _contains_any(image_ref[:idx], ":.") and image_ref[:idx] != "localhost"
+ ):
result["hostname"], remainder = default_domain, image_ref
else:
- result["hostname"], remainder = image_ref[:idx], image_ref[idx + 1:]
+ result["hostname"], remainder = image_ref[:idx], image_ref[idx + 1:] # fmt: skip
# Parse remainder information
idx = remainder.find("@")
if idx > 0 and len(remainder) > (idx + 1):
# docker image reference with digest
- component, result["digest"] = remainder[:idx], remainder[idx + 1:]
+ component, result["digest"] = remainder[:idx], remainder[idx + 1:] # fmt: skip
err = is_valid_digest(result["digest"])
if err:
if module:
@@ -88,7 +95,7 @@ def parse_docker_image_ref(image_ref, module=None):
idx = remainder.find(":")
if idx > 0 and len(remainder) > (idx + 1):
# docker image reference with tag
- component, result["tag"] = remainder[:idx], remainder[idx + 1:]
+ component, result["tag"] = remainder[:idx], remainder[idx + 1:] # fmt: skip
else:
# name only
component = remainder
@@ -96,8 +103,6 @@ def parse_docker_image_ref(image_ref, module=None):
namespace = None
if len(v) > 1:
namespace = v[0]
- result.update({
- "namespace": namespace, "name": v[-1]
- })
+ result.update({"namespace": namespace, "name": v[-1]})
return result, None
diff --git a/plugins/module_utils/openshift_groups.py b/plugins/module_utils/openshift_groups.py
index 5d1aaad..473a14f 100644
--- a/plugins/module_utils/openshift_groups.py
+++ b/plugins/module_utils/openshift_groups.py
@@ -3,11 +3,11 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-from __future__ import (absolute_import, division, print_function)
+from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
-import traceback
from datetime import datetime
from ansible.module_utils.parsing.convert_bool import boolean
@@ -19,18 +19,21 @@ from ansible_collections.community.okd.plugins.module_utils.openshift_ldap impor
ldap_split_host_port,
OpenshiftLDAPRFC2307,
OpenshiftLDAPActiveDirectory,
- OpenshiftLDAPAugmentedActiveDirectory
+ OpenshiftLDAPAugmentedActiveDirectory,
)
try:
import ldap
+
HAS_PYTHON_LDAP = True
PYTHON_LDAP_ERROR = None
except ImportError as e:
HAS_PYTHON_LDAP = False
PYTHON_LDAP_ERROR = e
-from ansible_collections.community.okd.plugins.module_utils.openshift_common import AnsibleOpenshiftModule
+from ansible_collections.community.okd.plugins.module_utils.openshift_common import (
+ AnsibleOpenshiftModule,
+)
try:
from kubernetes.dynamic.exceptions import DynamicApiError
@@ -44,7 +47,9 @@ LDAP_OPENSHIFT_UID_ANNOTATION = "openshift.io/ldap.uid"
LDAP_OPENSHIFT_SYNCTIME_ANNOTATION = "openshift.io/ldap.sync-time"
-def connect_to_ldap(module, server_uri, bind_dn=None, bind_pw=None, insecure=True, ca_file=None):
+def connect_to_ldap(
+ module, server_uri, bind_dn=None, bind_pw=None, insecure=True, ca_file=None
+):
if insecure:
ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
elif ca_file:
@@ -56,27 +61,36 @@ def connect_to_ldap(module, server_uri, bind_dn=None, bind_pw=None, insecure=Tru
connection.simple_bind_s(bind_dn, bind_pw)
return connection
except ldap.LDAPError as e:
- module.fail_json(msg="Cannot bind to the LDAP server '{0}' due to: {1}".format(server_uri, e))
+ module.fail_json(
+ msg="Cannot bind to the LDAP server '{0}' due to: {1}".format(server_uri, e)
+ )
def validate_group_annotation(definition, host_ip):
- name = definition['metadata']['name']
+ name = definition["metadata"]["name"]
# Validate LDAP URL Annotation
- annotate_url = definition['metadata'].get('annotations', {}).get(LDAP_OPENSHIFT_URL_ANNOTATION)
+ annotate_url = (
+ definition["metadata"].get("annotations", {}).get(LDAP_OPENSHIFT_URL_ANNOTATION)
+ )
if host_ip:
if not annotate_url:
- return "group '{0}' marked as having been synced did not have an '{1}' annotation".format(name, LDAP_OPENSHIFT_URL_ANNOTATION)
+ return "group '{0}' marked as having been synced did not have an '{1}' annotation".format(
+ name, LDAP_OPENSHIFT_URL_ANNOTATION
+ )
elif annotate_url != host_ip:
return "group '{0}' was not synchronized from: '{1}'".format(name, host_ip)
# Validate LDAP UID Annotation
- annotate_uid = definition['metadata']['annotations'].get(LDAP_OPENSHIFT_UID_ANNOTATION)
+ annotate_uid = definition["metadata"]["annotations"].get(
+ LDAP_OPENSHIFT_UID_ANNOTATION
+ )
if not annotate_uid:
- return "group '{0}' marked as having been synced did not have an '{1}' annotation".format(name, LDAP_OPENSHIFT_UID_ANNOTATION)
+ return "group '{0}' marked as having been synced did not have an '{1}' annotation".format(
+ name, LDAP_OPENSHIFT_UID_ANNOTATION
+ )
return None
class OpenshiftLDAPGroups(object):
-
kind = "Group"
version = "user.openshift.io/v1"
@@ -88,11 +102,7 @@ class OpenshiftLDAPGroups(object):
@property
def k8s_group_api(self):
if not self.__group_api:
- params = dict(
- kind=self.kind,
- api_version=self.version,
- fail=True
- )
+ params = dict(kind=self.kind, api_version=self.version, fail=True)
self.__group_api = self.module.find_resource(**params)
return self.__group_api
@@ -139,16 +149,26 @@ class OpenshiftLDAPGroups(object):
if missing:
self.module.fail_json(
- msg="The following groups were not found: %s" % ''.join(missing)
+ msg="The following groups were not found: %s" % "".join(missing)
)
else:
label_selector = "%s=%s" % (LDAP_OPENSHIFT_HOST_LABEL, host)
- resources = self.get_group_info(label_selectors=[label_selector], return_list=True)
+ resources = self.get_group_info(
+ label_selectors=[label_selector], return_list=True
+ )
if not resources:
- return None, "Unable to find Group matching label selector '%s'" % label_selector
+ return (
+ None,
+ "Unable to find Group matching label selector '%s'"
+ % label_selector,
+ )
groups = resources
if deny_groups:
- groups = [item for item in groups if item["metadata"]["name"] not in deny_groups]
+ groups = [
+ item
+ for item in groups
+ if item["metadata"]["name"] not in deny_groups
+ ]
uids = []
for grp in groups:
@@ -156,7 +176,9 @@ class OpenshiftLDAPGroups(object):
if err and allow_groups:
# We raise an error for group part of the allow_group not matching LDAP sync criteria
return None, err
- group_uid = grp['metadata']['annotations'].get(LDAP_OPENSHIFT_UID_ANNOTATION)
+ group_uid = grp["metadata"]["annotations"].get(
+ LDAP_OPENSHIFT_UID_ANNOTATION
+ )
self.cache[group_uid] = grp
uids.append(group_uid)
return uids, None
@@ -174,38 +196,65 @@ class OpenshiftLDAPGroups(object):
"kind": "Group",
"metadata": {
"name": group_name,
- "labels": {
- LDAP_OPENSHIFT_HOST_LABEL: self.module.host
- },
+ "labels": {LDAP_OPENSHIFT_HOST_LABEL: self.module.host},
"annotations": {
LDAP_OPENSHIFT_URL_ANNOTATION: self.module.netlocation,
LDAP_OPENSHIFT_UID_ANNOTATION: group_uid,
- }
- }
+ },
+ },
}
# Make sure we aren't taking over an OpenShift group that is already related to a different LDAP group
- ldaphost_label = group["metadata"].get("labels", {}).get(LDAP_OPENSHIFT_HOST_LABEL)
+ ldaphost_label = (
+ group["metadata"].get("labels", {}).get(LDAP_OPENSHIFT_HOST_LABEL)
+ )
if not ldaphost_label or ldaphost_label != self.module.host:
- return None, "Group %s: %s label did not match sync host: wanted %s, got %s" % (
- group_name, LDAP_OPENSHIFT_HOST_LABEL, self.module.host, ldaphost_label
+ return (
+ None,
+ "Group %s: %s label did not match sync host: wanted %s, got %s"
+ % (
+ group_name,
+ LDAP_OPENSHIFT_HOST_LABEL,
+ self.module.host,
+ ldaphost_label,
+ ),
)
- ldapurl_annotation = group["metadata"].get("annotations", {}).get(LDAP_OPENSHIFT_URL_ANNOTATION)
+ ldapurl_annotation = (
+ group["metadata"].get("annotations", {}).get(LDAP_OPENSHIFT_URL_ANNOTATION)
+ )
if not ldapurl_annotation or ldapurl_annotation != self.module.netlocation:
- return None, "Group %s: %s annotation did not match sync host: wanted %s, got %s" % (
- group_name, LDAP_OPENSHIFT_URL_ANNOTATION, self.module.netlocation, ldapurl_annotation
+ return (
+ None,
+ "Group %s: %s annotation did not match sync host: wanted %s, got %s"
+ % (
+ group_name,
+ LDAP_OPENSHIFT_URL_ANNOTATION,
+ self.module.netlocation,
+ ldapurl_annotation,
+ ),
)
- ldapuid_annotation = group["metadata"].get("annotations", {}).get(LDAP_OPENSHIFT_UID_ANNOTATION)
+ ldapuid_annotation = (
+ group["metadata"].get("annotations", {}).get(LDAP_OPENSHIFT_UID_ANNOTATION)
+ )
if not ldapuid_annotation or ldapuid_annotation != group_uid:
- return None, "Group %s: %s annotation did not match LDAP UID: wanted %s, got %s" % (
- group_name, LDAP_OPENSHIFT_UID_ANNOTATION, group_uid, ldapuid_annotation
+ return (
+ None,
+ "Group %s: %s annotation did not match LDAP UID: wanted %s, got %s"
+ % (
+ group_name,
+ LDAP_OPENSHIFT_UID_ANNOTATION,
+ group_uid,
+ ldapuid_annotation,
+ ),
)
# Overwrite Group Users data
group["users"] = usernames
- group["metadata"]["annotations"][LDAP_OPENSHIFT_SYNCTIME_ANNOTATION] = datetime.now().isoformat()
+ group["metadata"]["annotations"][
+ LDAP_OPENSHIFT_SYNCTIME_ANNOTATION
+ ] = datetime.now().isoformat()
return group, None
def create_openshift_groups(self, groups: list):
@@ -223,9 +272,15 @@ class OpenshiftLDAPGroups(object):
else:
definition = self.k8s_group_api.create(definition).to_dict()
except DynamicApiError as exc:
- self.module.fail_json(msg="Failed to %s Group '%s' due to: %s" % (method, name, exc.body))
+ self.module.fail_json(
+ msg="Failed to %s Group '%s' due to: %s"
+ % (method, name, exc.body)
+ )
except Exception as exc:
- self.module.fail_json(msg="Failed to %s Group '%s' due to: %s" % (method, name, to_native(exc)))
+ self.module.fail_json(
+ msg="Failed to %s Group '%s' due to: %s"
+ % (method, name, to_native(exc))
+ )
equals = False
if existing:
equals, diff = self.module.diff_objects(existing, definition)
@@ -235,27 +290,27 @@ class OpenshiftLDAPGroups(object):
return results, diffs, changed
def delete_openshift_group(self, name: str):
- result = dict(
- kind=self.kind,
- apiVersion=self.version,
- metadata=dict(
- name=name
- )
- )
+ result = dict(kind=self.kind, apiVersion=self.version, metadata=dict(name=name))
if not self.module.check_mode:
try:
result = self.k8s_group_api.delete(name=name).to_dict()
except DynamicApiError as exc:
- self.module.fail_json(msg="Failed to delete Group '{0}' due to: {1}".format(name, exc.body))
+ self.module.fail_json(
+ msg="Failed to delete Group '{0}' due to: {1}".format(
+ name, exc.body
+ )
+ )
except Exception as exc:
- self.module.fail_json(msg="Failed to delete Group '{0}' due to: {1}".format(name, to_native(exc)))
+ self.module.fail_json(
+ msg="Failed to delete Group '{0}' due to: {1}".format(
+ name, to_native(exc)
+ )
+ )
return result
class OpenshiftGroupsSync(AnsibleOpenshiftModule):
-
def __init__(self, **kwargs):
-
super(OpenshiftGroupsSync, self).__init__(**kwargs)
self.__k8s_group_api = None
self.__ldap_connection = None
@@ -267,17 +322,14 @@ class OpenshiftGroupsSync(AnsibleOpenshiftModule):
if not HAS_PYTHON_LDAP:
self.fail_json(
- msg=missing_required_lib('python-ldap'), error=to_native(PYTHON_LDAP_ERROR)
+ msg=missing_required_lib("python-ldap"),
+ error=to_native(PYTHON_LDAP_ERROR),
)
@property
def k8s_group_api(self):
if not self.__k8s_group_api:
- params = dict(
- kind="Group",
- api_version="user.openshift.io/v1",
- fail=True
- )
+ params = dict(kind="Group", api_version="user.openshift.io/v1", fail=True)
self.__k8s_group_api = self.find_resource(**params)
return self.__k8s_group_api
@@ -291,11 +343,11 @@ class OpenshiftGroupsSync(AnsibleOpenshiftModule):
# Create connection object
params = dict(
module=self,
- server_uri=self.config.get('url'),
- bind_dn=self.config.get('bindDN'),
- bind_pw=self.config.get('bindPassword'),
- insecure=boolean(self.config.get('insecure')),
- ca_file=self.config.get('ca')
+ server_uri=self.config.get("url"),
+ bind_dn=self.config.get("bindDN"),
+ bind_pw=self.config.get("bindPassword"),
+ insecure=boolean(self.config.get("insecure")),
+ ca_file=self.config.get("ca"),
)
self.__ldap_connection = connect_to_ldap(**params)
return self.__ldap_connection
@@ -327,7 +379,6 @@ class OpenshiftGroupsSync(AnsibleOpenshiftModule):
return syncer
def synchronize(self):
-
sync_group_type = self.module.params.get("type")
groups_uids = []
@@ -365,7 +416,8 @@ class OpenshiftGroupsSync(AnsibleOpenshiftModule):
name, err = syncer.get_username_for_entry(entry)
if err:
self.exit_json(
- msg="Unable to determine username for entry %s: %s" % (entry, err)
+ msg="Unable to determine username for entry %s: %s"
+ % (entry, err)
)
if isinstance(name, list):
usernames.extend(name)
@@ -380,13 +432,17 @@ class OpenshiftGroupsSync(AnsibleOpenshiftModule):
self.exit_json(msg=err)
# Make Openshift group
- group, err = ldap_openshift_group.make_openshift_group(uid, group_name, usernames)
+ group, err = ldap_openshift_group.make_openshift_group(
+ uid, group_name, usernames
+ )
if err:
self.fail_json(msg=err)
openshift_groups.append(group)
# Create Openshift Groups
- results, diffs, changed = ldap_openshift_group.create_openshift_groups(openshift_groups)
+ results, diffs, changed = ldap_openshift_group.create_openshift_groups(
+ openshift_groups
+ )
self.module.exit_json(changed=True, groups=results)
def prune(self):
@@ -404,7 +460,10 @@ class OpenshiftGroupsSync(AnsibleOpenshiftModule):
# Check if LDAP group exist
exists, err = syncer.is_ldapgroup_exists(uid)
if err:
- msg = "Error determining LDAP group existence for group %s: %s" % (uid, err)
+ msg = "Error determining LDAP group existence for group %s: %s" % (
+ uid,
+ err,
+ )
self.module.fail_json(msg=msg)
if exists:
@@ -429,14 +488,22 @@ class OpenshiftGroupsSync(AnsibleOpenshiftModule):
self.fail_json(msg="Invalid LDAP Sync config: %s" % error)
# Split host/port
- if self.config.get('url'):
- result, error = ldap_split_host_port(self.config.get('url'))
+ if self.config.get("url"):
+ result, error = ldap_split_host_port(self.config.get("url"))
if error:
- self.fail_json(msg="Failed to parse url='{0}': {1}".format(self.config.get('url'), error))
- self.netlocation, self.host, self.port = result["netlocation"], result["host"], result["port"]
+ self.fail_json(
+ msg="Failed to parse url='{0}': {1}".format(
+ self.config.get("url"), error
+ )
+ )
+ self.netlocation, self.host, self.port = (
+ result["netlocation"],
+ result["host"],
+ result["port"],
+ )
self.scheme = result["scheme"]
- if self.params.get('state') == 'present':
+ if self.params.get("state") == "present":
self.synchronize()
else:
self.prune()
diff --git a/plugins/module_utils/openshift_images_common.py b/plugins/module_utils/openshift_images_common.py
index 67d7123..8978a93 100644
--- a/plugins/module_utils/openshift_images_common.py
+++ b/plugins/module_utils/openshift_images_common.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python
-from __future__ import (absolute_import, division, print_function)
+from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
from datetime import datetime
@@ -17,9 +18,9 @@ def get_image_blobs(image):
return blobs, "failed to read metadata for image %s" % image["metadata"]["name"]
media_type_manifest = (
"application/vnd.docker.distribution.manifest.v2+json",
- "application/vnd.oci.image.manifest.v1+json"
+ "application/vnd.oci.image.manifest.v1+json",
)
- media_type_has_config = image['dockerImageManifestMediaType'] in media_type_manifest
+ media_type_has_config = image["dockerImageManifestMediaType"] in media_type_manifest
docker_image_id = docker_image_metadata.get("Id")
if media_type_has_config and docker_image_id and len(docker_image_id) > 0:
blobs.append(docker_image_id)
@@ -29,19 +30,18 @@ def get_image_blobs(image):
def is_created_after(creation_timestamp, max_creation_timestamp):
if not max_creation_timestamp:
return False
- creationTimestamp = datetime.strptime(creation_timestamp, '%Y-%m-%dT%H:%M:%SZ')
+ creationTimestamp = datetime.strptime(creation_timestamp, "%Y-%m-%dT%H:%M:%SZ")
return creationTimestamp > max_creation_timestamp
def is_too_young_object(obj, max_creation_timestamp):
- return is_created_after(obj['metadata']['creationTimestamp'],
- max_creation_timestamp)
+ return is_created_after(
+ obj["metadata"]["creationTimestamp"], max_creation_timestamp
+ )
class OpenShiftAnalyzeImageStream(object):
-
def __init__(self, ignore_invalid_refs, max_creation_timestamp, module):
-
self.max_creationTimestamp = max_creation_timestamp
self.used_tags = {}
self.used_images = {}
@@ -53,32 +53,34 @@ class OpenShiftAnalyzeImageStream(object):
if error:
return error
- if not result['hostname'] or not result['namespace']:
+ if not result["hostname"] or not result["namespace"]:
# image reference does not match hostname/namespace/name pattern - skipping
return None
- if not result['digest']:
+ if not result["digest"]:
# Attempt to dereference istag. Since we cannot be sure whether the reference refers to the
# integrated registry or not, we ignore the host part completely. As a consequence, we may keep
# image otherwise sentenced for a removal just because its pull spec accidentally matches one of
# our imagestreamtags.
# set the tag if empty
- if result['tag'] == "":
- result['tag'] = 'latest'
- key = "%s/%s:%s" % (result['namespace'], result['name'], result['tag'])
+ if result["tag"] == "":
+ result["tag"] = "latest"
+ key = "%s/%s:%s" % (result["namespace"], result["name"], result["tag"])
if key not in self.used_tags:
self.used_tags[key] = []
self.used_tags[key].append(referrer)
else:
- key = "%s/%s@%s" % (result['namespace'], result['name'], result['digest'])
+ key = "%s/%s@%s" % (result["namespace"], result["name"], result["digest"])
if key not in self.used_images:
self.used_images[key] = []
self.used_images[key].append(referrer)
def analyze_refs_from_pod_spec(self, podSpec, referrer):
- for container in podSpec.get('initContainers', []) + podSpec.get('containers', []):
- image = container.get('image')
+ for container in podSpec.get("initContainers", []) + podSpec.get(
+ "containers", []
+ ):
+ image = container.get("image")
if len(image.strip()) == 0:
# Ignoring container because it has no reference to image
continue
@@ -93,29 +95,35 @@ class OpenShiftAnalyzeImageStream(object):
# pending or running. Additionally, it has to be at least as old as the minimum
# age threshold defined by the algorithm.
too_young = is_too_young_object(pod, self.max_creationTimestamp)
- if pod['status']['phase'] not in ("Running", "Pending") and too_young:
+ if pod["status"]["phase"] not in ("Running", "Pending") and too_young:
continue
referrer = {
"kind": pod["kind"],
"namespace": pod["metadata"]["namespace"],
"name": pod["metadata"]["name"],
}
- err = self.analyze_refs_from_pod_spec(pod['spec'], referrer)
+ err = self.analyze_refs_from_pod_spec(pod["spec"], referrer)
if err:
return err
return None
def analyze_refs_pod_creators(self, resources):
keys = (
- "ReplicationController", "DeploymentConfig", "DaemonSet",
- "Deployment", "ReplicaSet", "StatefulSet", "Job", "CronJob"
+ "ReplicationController",
+ "DeploymentConfig",
+ "DaemonSet",
+ "Deployment",
+ "ReplicaSet",
+ "StatefulSet",
+ "Job",
+ "CronJob",
)
for k, objects in iteritems(resources):
if k not in keys:
continue
for obj in objects:
- if k == 'CronJob':
+ if k == "CronJob":
spec = obj["spec"]["jobTemplate"]["spec"]["template"]["spec"]
else:
spec = obj["spec"]["template"]["spec"]
@@ -132,64 +140,84 @@ class OpenShiftAnalyzeImageStream(object):
def analyze_refs_from_strategy(self, build_strategy, namespace, referrer):
# Determine 'from' reference
def _determine_source_strategy():
- for src in ('sourceStrategy', 'dockerStrategy', 'customStrategy'):
+ for src in ("sourceStrategy", "dockerStrategy", "customStrategy"):
strategy = build_strategy.get(src)
if strategy:
- return strategy.get('from')
+ return strategy.get("from")
return None
def _parse_image_stream_image_name(name):
- v = name.split('@')
+ v = name.split("@")
if len(v) != 2:
- return None, None, "expected exactly one @ in the isimage name %s" % name
+ return (
+ None,
+ None,
+ "expected exactly one @ in the isimage name %s" % name,
+ )
name = v[0]
tag = v[1]
if len(name) == 0 or len(tag) == 0:
- return None, None, "image stream image name %s must have a name and ID" % name
+ return (
+ None,
+ None,
+ "image stream image name %s must have a name and ID" % name,
+ )
return name, tag, None
def _parse_image_stream_tag_name(name):
if "@" in name:
- return None, None, "%s is an image stream image, not an image stream tag" % name
+ return (
+ None,
+ None,
+ "%s is an image stream image, not an image stream tag" % name,
+ )
v = name.split(":")
if len(v) != 2:
- return None, None, "expected exactly one : delimiter in the istag %s" % name
+ return (
+ None,
+ None,
+ "expected exactly one : delimiter in the istag %s" % name,
+ )
name = v[0]
tag = v[1]
if len(name) == 0 or len(tag) == 0:
- return None, None, "image stream tag name %s must have a name and a tag" % name
+ return (
+ None,
+ None,
+ "image stream tag name %s must have a name and a tag" % name,
+ )
return name, tag, None
from_strategy = _determine_source_strategy()
if from_strategy:
- if from_strategy.get('kind') == "DockerImage":
- docker_image_ref = from_strategy.get('name').strip()
+ if from_strategy.get("kind") == "DockerImage":
+ docker_image_ref = from_strategy.get("name").strip()
if len(docker_image_ref) > 0:
err = self.analyze_reference_image(docker_image_ref, referrer)
- elif from_strategy.get('kind') == "ImageStreamImage":
- name, tag, error = _parse_image_stream_image_name(from_strategy.get('name'))
+ elif from_strategy.get("kind") == "ImageStreamImage":
+ name, tag, error = _parse_image_stream_image_name(
+ from_strategy.get("name")
+ )
if error:
if not self.ignore_invalid_refs:
return error
else:
- namespace = from_strategy.get('namespace') or namespace
- self.used_images.append({
- 'namespace': namespace,
- 'name': name,
- 'tag': tag
- })
- elif from_strategy.get('kind') == "ImageStreamTag":
- name, tag, error = _parse_image_stream_tag_name(from_strategy.get('name'))
+ namespace = from_strategy.get("namespace") or namespace
+ self.used_images.append(
+ {"namespace": namespace, "name": name, "tag": tag}
+ )
+ elif from_strategy.get("kind") == "ImageStreamTag":
+ name, tag, error = _parse_image_stream_tag_name(
+ from_strategy.get("name")
+ )
if error:
if not self.ignore_invalid_refs:
return error
else:
- namespace = from_strategy.get('namespace') or namespace
- self.used_tags.append({
- 'namespace': namespace,
- 'name': name,
- 'tag': tag
- })
+ namespace = from_strategy.get("namespace") or namespace
+ self.used_tags.append(
+ {"namespace": namespace, "name": name, "tag": tag}
+ )
def analyze_refs_from_build_strategy(self, resources):
# Json Path is always spec.strategy
@@ -203,16 +231,20 @@ class OpenShiftAnalyzeImageStream(object):
"namespace": obj["metadata"]["namespace"],
"name": obj["metadata"]["name"],
}
- error = self.analyze_refs_from_strategy(obj['spec']['strategy'],
- obj['metadata']['namespace'],
- referrer)
+ error = self.analyze_refs_from_strategy(
+ obj["spec"]["strategy"], obj["metadata"]["namespace"], referrer
+ )
if error is not None:
- return "%s/%s/%s: %s" % (referrer["kind"], referrer["namespace"], referrer["name"], error)
+ return "%s/%s/%s: %s" % (
+ referrer["kind"],
+ referrer["namespace"],
+ referrer["name"],
+ error,
+ )
def analyze_image_stream(self, resources):
-
# Analyze image reference from Pods
- error = self.analyze_refs_from_pods(resources['Pod'])
+ error = self.analyze_refs_from_pods(resources["Pod"])
if error:
return None, None, error
diff --git a/plugins/module_utils/openshift_import_image.py b/plugins/module_utils/openshift_import_image.py
index 01bba82..c9953d7 100644
--- a/plugins/module_utils/openshift_import_image.py
+++ b/plugins/module_utils/openshift_import_image.py
@@ -1,16 +1,17 @@
#!/usr/bin/env python
-from __future__ import (absolute_import, division, print_function)
+from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
-import traceback
import copy
-from ansible.module_utils._text import to_native
from ansible.module_utils.parsing.convert_bool import boolean
from ansible.module_utils.six import string_types
-from ansible_collections.community.okd.plugins.module_utils.openshift_common import AnsibleOpenshiftModule
+from ansible_collections.community.okd.plugins.module_utils.openshift_common import (
+ AnsibleOpenshiftModule,
+)
try:
from kubernetes.dynamic.exceptions import DynamicApiError
@@ -44,10 +45,17 @@ def follow_imagestream_tag_reference(stream, tag):
return name, tag, len(parts) == 2
content = []
- err_cross_stream_ref = "tag %s points to an imagestreamtag from another ImageStream" % tag
+ err_cross_stream_ref = (
+ "tag %s points to an imagestreamtag from another ImageStream" % tag
+ )
while True:
if tag in content:
- return tag, None, multiple, "tag %s on the image stream is a reference to same tag" % tag
+ return (
+ tag,
+ None,
+ multiple,
+ "tag %s on the image stream is a reference to same tag" % tag,
+ )
content.append(tag)
tag_ref = _imagestream_has_tag()
if not tag_ref:
@@ -56,7 +64,10 @@ def follow_imagestream_tag_reference(stream, tag):
if not tag_ref.get("from") or tag_ref["from"]["kind"] != "ImageStreamTag":
return tag, tag_ref, multiple, None
- if tag_ref["from"]["namespace"] != "" and tag_ref["from"]["namespace"] != stream["metadata"]["namespace"]:
+ if (
+ tag_ref["from"]["namespace"] != ""
+ and tag_ref["from"]["namespace"] != stream["metadata"]["namespace"]
+ ):
return tag, None, multiple, err_cross_stream_ref
# The reference needs to be followed with two format patterns:
@@ -64,7 +75,12 @@ def follow_imagestream_tag_reference(stream, tag):
if ":" in tag_ref["from"]["name"]:
name, tagref, result = _imagestream_split_tag(tag_ref["from"]["name"])
if not result:
- return tag, None, multiple, "tag %s points to an invalid imagestreamtag" % tag
+ return (
+ tag,
+ None,
+ multiple,
+ "tag %s points to an invalid imagestreamtag" % tag,
+ )
if name != stream["metadata"]["namespace"]:
# anotheris:sometag - this should not happen.
return tag, None, multiple, err_cross_stream_ref
@@ -80,7 +96,7 @@ class OpenShiftImportImage(AnsibleOpenshiftModule):
super(OpenShiftImportImage, self).__init__(**kwargs)
self._rest_client = None
- self.registryhost = self.params.get('registry_url')
+ self.registryhost = self.params.get("registry_url")
self.changed = False
ref_policy = self.params.get("reference_policy")
@@ -90,9 +106,7 @@ class OpenShiftImportImage(AnsibleOpenshiftModule):
elif ref_policy == "local":
ref_policy_type = "Local"
- self.ref_policy = {
- "type": ref_policy_type
- }
+ self.ref_policy = {"type": ref_policy_type}
self.validate_certs = self.params.get("validate_registry_certs")
self.cluster_resources = {}
@@ -104,15 +118,15 @@ class OpenShiftImportImage(AnsibleOpenshiftModule):
"metadata": {
"name": stream["metadata"]["name"],
"namespace": stream["metadata"]["namespace"],
- "resourceVersion": stream["metadata"].get("resourceVersion")
+ "resourceVersion": stream["metadata"].get("resourceVersion"),
},
- "spec": {
- "import": True
- }
+ "spec": {"import": True},
}
annotations = stream.get("annotations", {})
- insecure = boolean(annotations.get("openshift.io/image.insecureRepository", True))
+ insecure = boolean(
+ annotations.get("openshift.io/image.insecureRepository", True)
+ )
if self.validate_certs is not None:
insecure = not self.validate_certs
return isi, insecure
@@ -126,7 +140,7 @@ class OpenShiftImportImage(AnsibleOpenshiftModule):
},
"importPolicy": {
"insecure": insecure,
- "scheduled": self.params.get("scheduled")
+ "scheduled": self.params.get("scheduled"),
},
"referencePolicy": self.ref_policy,
}
@@ -149,26 +163,23 @@ class OpenShiftImportImage(AnsibleOpenshiftModule):
scheduled = scheduled or old_tag["importPolicy"].get("scheduled")
images = isi["spec"].get("images", [])
- images.append({
- "from": {
- "kind": "DockerImage",
- "name": tags.get(k),
- },
- "to": {
- "name": k
- },
- "importPolicy": {
- "insecure": insecure,
- "scheduled": scheduled
- },
- "referencePolicy": self.ref_policy,
- })
+ images.append(
+ {
+ "from": {
+ "kind": "DockerImage",
+ "name": tags.get(k),
+ },
+ "to": {"name": k},
+ "importPolicy": {"insecure": insecure, "scheduled": scheduled},
+ "referencePolicy": self.ref_policy,
+ }
+ )
isi["spec"]["images"] = images
return isi
def create_image_stream(self, ref):
"""
- Create new ImageStream and accompanying ImageStreamImport
+ Create new ImageStream and accompanying ImageStreamImport
"""
source = self.params.get("source")
if not source:
@@ -183,27 +194,20 @@ class OpenShiftImportImage(AnsibleOpenshiftModule):
),
)
if self.params.get("all") and not ref["tag"]:
- spec = dict(
- dockerImageRepository=source
- )
+ spec = dict(dockerImageRepository=source)
isi = self.create_image_stream_import_all(stream, source)
else:
spec = dict(
tags=[
{
- "from": {
- "kind": "DockerImage",
- "name": source
- },
- "referencePolicy": self.ref_policy
+ "from": {"kind": "DockerImage", "name": source},
+ "referencePolicy": self.ref_policy,
}
]
)
tags = {ref["tag"]: source}
isi = self.create_image_stream_import_tags(stream, tags)
- stream.update(
- dict(spec=spec)
- )
+ stream.update(dict(spec=spec))
return stream, isi
def import_all(self, istream):
@@ -220,8 +224,9 @@ class OpenShiftImportImage(AnsibleOpenshiftModule):
if t.get("from") and t["from"].get("kind") == "DockerImage":
tags[t.get("name")] = t["from"].get("name")
if tags == {}:
- msg = "image stream %s/%s does not have tags pointing to external container images" % (
- stream["metadata"]["namespace"], stream["metadata"]["name"]
+ msg = (
+ "image stream %s/%s does not have tags pointing to external container images"
+ % (stream["metadata"]["namespace"], stream["metadata"]["name"])
)
self.fail_json(msg=msg)
isi = self.create_image_stream_import_tags(stream, tags)
@@ -236,7 +241,9 @@ class OpenShiftImportImage(AnsibleOpenshiftModule):
source = self.params.get("source")
# Follow any referential tags to the destination
- final_tag, existing, multiple, err = follow_imagestream_tag_reference(stream, tag)
+ final_tag, existing, multiple, err = follow_imagestream_tag_reference(
+ stream, tag
+ )
if err:
if err == err_stream_not_found_ref:
# Create a new tag
@@ -245,7 +252,10 @@ class OpenShiftImportImage(AnsibleOpenshiftModule):
# if the from is still empty this means there's no such tag defined
# nor we can't create any from .spec.dockerImageRepository
if not source:
- msg = "the tag %s does not exist on the image stream - choose an existing tag to import" % tag
+ msg = (
+ "the tag %s does not exist on the image stream - choose an existing tag to import"
+ % tag
+ )
self.fail_json(msg=msg)
existing = {
"from": {
@@ -257,13 +267,21 @@ class OpenShiftImportImage(AnsibleOpenshiftModule):
self.fail_json(msg=err)
else:
# Disallow re-importing anything other than DockerImage
- if existing.get("from", {}) and existing["from"].get("kind") != "DockerImage":
+ if (
+ existing.get("from", {})
+ and existing["from"].get("kind") != "DockerImage"
+ ):
msg = "tag {tag} points to existing {kind}/={name}, it cannot be re-imported.".format(
- tag=tag, kind=existing["from"]["kind"], name=existing["from"]["name"]
+ tag=tag,
+ kind=existing["from"]["kind"],
+ name=existing["from"]["name"],
)
# disallow changing an existing tag
if not existing.get("from", {}):
- msg = "tag %s already exists - you cannot change the source using this module." % tag
+ msg = (
+ "tag %s already exists - you cannot change the source using this module."
+ % tag
+ )
self.fail_json(msg=msg)
if source and source != existing["from"]["name"]:
if multiple:
@@ -271,7 +289,10 @@ class OpenShiftImportImage(AnsibleOpenshiftModule):
tag, final_tag, existing["from"]["name"]
)
else:
- msg = "the tag %s points to %s you cannot change the source using this module." % (tag, final_tag)
+ msg = (
+ "the tag %s points to %s you cannot change the source using this module."
+ % (tag, final_tag)
+ )
self.fail_json(msg=msg)
# Set the target item to import
@@ -309,13 +330,13 @@ class OpenShiftImportImage(AnsibleOpenshiftModule):
kind=kind,
api_version=api_version,
name=ref.get("name"),
- namespace=self.params.get("namespace")
+ namespace=self.params.get("namespace"),
)
result = self.kubernetes_facts(**params)
if not result["api_found"]:
msg = 'Failed to find API for resource with apiVersion "{0}" and kind "{1}"'.format(
api_version, kind
- ),
+ )
self.fail_json(msg=msg)
imagestream = None
if len(result["resources"]) > 0:
@@ -335,7 +356,9 @@ class OpenShiftImportImage(AnsibleOpenshiftModule):
def parse_image_reference(self, image_ref):
result, err = parse_docker_image_ref(image_ref, self.module)
if result.get("digest"):
- self.fail_json(msg="Cannot import by ID, error with definition: %s" % image_ref)
+ self.fail_json(
+ msg="Cannot import by ID, error with definition: %s" % image_ref
+ )
tag = result.get("tag") or None
if not self.params.get("all") and not tag:
tag = "latest"
@@ -345,7 +368,6 @@ class OpenShiftImportImage(AnsibleOpenshiftModule):
return dict(name=result.get("name"), tag=tag, source=image_ref)
def execute_module(self):
-
names = []
name = self.params.get("name")
if isinstance(name, string_types):
diff --git a/plugins/module_utils/openshift_ldap.py b/plugins/module_utils/openshift_ldap.py
index bb9229a..cb19774 100644
--- a/plugins/module_utils/openshift_ldap.py
+++ b/plugins/module_utils/openshift_ldap.py
@@ -3,7 +3,8 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-from __future__ import (absolute_import, division, print_function)
+from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
@@ -24,109 +25,119 @@ LDAP_SEARCH_OUT_OF_SCOPE_ERROR = "trying to search by DN for an entry that exist
def validate_ldap_sync_config(config):
# Validate url
- url = config.get('url')
+ url = config.get("url")
if not url:
return "url should be non empty attribute."
# Make sure bindDN and bindPassword are both set, or both unset
- bind_dn = config.get('bindDN', "")
- bind_password = config.get('bindPassword', "")
+ bind_dn = config.get("bindDN", "")
+ bind_password = config.get("bindPassword", "")
if (len(bind_dn) == 0) != (len(bind_password) == 0):
return "bindDN and bindPassword must both be specified, or both be empty."
- insecure = boolean(config.get('insecure'))
- ca_file = config.get('ca')
+ insecure = boolean(config.get("insecure"))
+ ca_file = config.get("ca")
if insecure:
- if url.startswith('ldaps://'):
+ if url.startswith("ldaps://"):
return "Cannot use ldaps scheme with insecure=true."
if ca_file:
return "Cannot specify a ca with insecure=true."
elif ca_file and not os.path.isfile(ca_file):
return "could not read ca file: {0}.".format(ca_file)
- nameMapping = config.get('groupUIDNameMapping', {})
+ nameMapping = config.get("groupUIDNameMapping", {})
for k, v in iteritems(nameMapping):
if len(k) == 0 or len(v) == 0:
return "groupUIDNameMapping has empty key or value"
schemas = []
- schema_list = ('rfc2307', 'activeDirectory', 'augmentedActiveDirectory')
+ schema_list = ("rfc2307", "activeDirectory", "augmentedActiveDirectory")
for schema in schema_list:
if schema in config:
schemas.append(schema)
if len(schemas) == 0:
- return "No schema-specific config was provided, should be one of %s" % ", ".join(schema_list)
+ return (
+ "No schema-specific config was provided, should be one of %s"
+ % ", ".join(schema_list)
+ )
if len(schemas) > 1:
- return "Exactly one schema-specific config is required; found (%d) %s" % (len(schemas), ','.join(schemas))
+ return "Exactly one schema-specific config is required; found (%d) %s" % (
+ len(schemas),
+ ",".join(schemas),
+ )
- if schemas[0] == 'rfc2307':
+ if schemas[0] == "rfc2307":
return validate_RFC2307(config.get("rfc2307"))
- elif schemas[0] == 'activeDirectory':
+ elif schemas[0] == "activeDirectory":
return validate_ActiveDirectory(config.get("activeDirectory"))
- elif schemas[0] == 'augmentedActiveDirectory':
+ elif schemas[0] == "augmentedActiveDirectory":
return validate_AugmentedActiveDirectory(config.get("augmentedActiveDirectory"))
def validate_ldap_query(qry, isDNOnly=False):
-
# validate query scope
- scope = qry.get('scope')
+ scope = qry.get("scope")
if scope and scope not in ("", "sub", "one", "base"):
return "invalid scope %s" % scope
# validate deref aliases
- derefAlias = qry.get('derefAliases')
+ derefAlias = qry.get("derefAliases")
if derefAlias and derefAlias not in ("never", "search", "base", "always"):
return "not a valid LDAP alias dereferncing behavior: %s", derefAlias
# validate timeout
- timeout = qry.get('timeout')
+ timeout = qry.get("timeout")
if timeout and float(timeout) < 0:
return "timeout must be equal to or greater than zero"
# Validate DN only
- qry_filter = qry.get('filter', "")
+ qry_filter = qry.get("filter", "")
if isDNOnly:
if len(qry_filter) > 0:
return 'cannot specify a filter when using "dn" as the UID attribute'
else:
# validate filter
- if len(qry_filter) == 0 or qry_filter[0] != '(':
+ if len(qry_filter) == 0 or qry_filter[0] != "(":
return "filter does not start with an '('"
return None
def validate_RFC2307(config):
- qry = config.get('groupsQuery')
+ qry = config.get("groupsQuery")
if not qry or not isinstance(qry, dict):
return "RFC2307: groupsQuery requires a dictionary"
error = validate_ldap_query(qry)
if not error:
return error
- for field in ('groupUIDAttribute', 'groupNameAttributes', 'groupMembershipAttributes',
- 'userUIDAttribute', 'userNameAttributes'):
+ for field in (
+ "groupUIDAttribute",
+ "groupNameAttributes",
+ "groupMembershipAttributes",
+ "userUIDAttribute",
+ "userNameAttributes",
+ ):
value = config.get(field)
if not value:
return "RFC2307: {0} is required.".format(field)
- users_qry = config.get('usersQuery')
+ users_qry = config.get("usersQuery")
if not users_qry or not isinstance(users_qry, dict):
return "RFC2307: usersQuery requires a dictionary"
- isUserDNOnly = (config.get('userUIDAttribute').strip() == 'dn')
+ isUserDNOnly = config.get("userUIDAttribute").strip() == "dn"
return validate_ldap_query(users_qry, isDNOnly=isUserDNOnly)
def validate_ActiveDirectory(config, label="ActiveDirectory"):
- users_qry = config.get('usersQuery')
+ users_qry = config.get("usersQuery")
if not users_qry or not isinstance(users_qry, dict):
return "{0}: usersQuery requires as dictionnary".format(label)
error = validate_ldap_query(users_qry)
if not error:
return error
- for field in ('userNameAttributes', 'groupMembershipAttributes'):
+ for field in ("userNameAttributes", "groupMembershipAttributes"):
value = config.get(field)
if not value:
return "{0}: {1} is required.".format(field, label)
@@ -138,24 +149,24 @@ def validate_AugmentedActiveDirectory(config):
error = validate_ActiveDirectory(config, label="AugmentedActiveDirectory")
if not error:
return error
- for field in ('groupUIDAttribute', 'groupNameAttributes'):
+ for field in ("groupUIDAttribute", "groupNameAttributes"):
value = config.get(field)
if not value:
return "AugmentedActiveDirectory: {0} is required".format(field)
- groups_qry = config.get('groupsQuery')
+ groups_qry = config.get("groupsQuery")
if not groups_qry or not isinstance(groups_qry, dict):
return "AugmentedActiveDirectory: groupsQuery requires as dictionnary."
- isGroupDNOnly = (config.get('groupUIDAttribute').strip() == 'dn')
+ isGroupDNOnly = config.get("groupUIDAttribute").strip() == "dn"
return validate_ldap_query(groups_qry, isDNOnly=isGroupDNOnly)
def determine_ldap_scope(scope):
if scope in ("", "sub"):
return ldap.SCOPE_SUBTREE
- elif scope == 'base':
+ elif scope == "base":
return ldap.SCOPE_BASE
- elif scope == 'one':
+ elif scope == "one":
return ldap.SCOPE_ONELEVEL
return None
@@ -175,28 +186,28 @@ def determine_deref_aliases(derefAlias):
def openshift_ldap_build_base_query(config):
qry = {}
- if config.get('baseDN'):
- qry['base'] = config.get('baseDN')
+ if config.get("baseDN"):
+ qry["base"] = config.get("baseDN")
- scope = determine_ldap_scope(config.get('scope'))
+ scope = determine_ldap_scope(config.get("scope"))
if scope:
- qry['scope'] = scope
+ qry["scope"] = scope
- pageSize = config.get('pageSize')
+ pageSize = config.get("pageSize")
if pageSize and int(pageSize) > 0:
- qry['sizelimit'] = int(pageSize)
+ qry["sizelimit"] = int(pageSize)
- timeout = config.get('timeout')
+ timeout = config.get("timeout")
if timeout and int(timeout) > 0:
- qry['timeout'] = int(timeout)
+ qry["timeout"] = int(timeout)
- filter = config.get('filter')
+ filter = config.get("filter")
if filter:
- qry['filterstr'] = filter
+ qry["filterstr"] = filter
- derefAlias = determine_deref_aliases(config.get('derefAliases'))
+ derefAlias = determine_deref_aliases(config.get("derefAliases"))
if derefAlias:
- qry['derefAlias'] = derefAlias
+ qry["derefAlias"] = derefAlias
return qry
@@ -205,32 +216,30 @@ def openshift_ldap_get_attribute_for_entry(entry, attribute):
if isinstance(attribute, list):
attributes = attribute
for k in attributes:
- if k.lower() == 'dn':
+ if k.lower() == "dn":
return entry[0]
v = entry[1].get(k, None)
if v:
if isinstance(v, list):
result = []
for x in v:
- if hasattr(x, 'decode'):
- result.append(x.decode('utf-8'))
+ if hasattr(x, "decode"):
+ result.append(x.decode("utf-8"))
else:
result.append(x)
return result
else:
- return v.decode('utf-8') if hasattr(v, 'decode') else v
+ return v.decode("utf-8") if hasattr(v, "decode") else v
return ""
def ldap_split_host_port(hostport):
"""
- ldap_split_host_port splits a network address of the form "host:port",
- "host%zone:port", "[host]:port" or "[host%zone]:port" into host or
- host%zone and port.
+ ldap_split_host_port splits a network address of the form "host:port",
+ "host%zone:port", "[host]:port" or "[host%zone]:port" into host or
+ host%zone and port.
"""
- result = dict(
- scheme=None, netlocation=None, host=None, port=None
- )
+ result = dict(scheme=None, netlocation=None, host=None, port=None)
if not hostport:
return result, None
@@ -240,10 +249,10 @@ def ldap_split_host_port(hostport):
if "://" in hostport:
idx = hostport.find(scheme_l)
result["scheme"] = hostport[:idx]
- netlocation = hostport[idx + len(scheme_l):]
+ netlocation = hostport[idx + len(scheme_l):] # fmt: skip
result["netlocation"] = netlocation
- if netlocation[-1] == ']':
+ if netlocation[-1] == "]":
# ipv6 literal (with no port)
result["host"] = netlocation
@@ -259,21 +268,32 @@ def ldap_split_host_port(hostport):
def openshift_ldap_query_for_entries(connection, qry, unique_entry=True):
# set deref alias (TODO: need to set a default value to reset for each transaction)
- derefAlias = qry.pop('derefAlias', None)
+ derefAlias = qry.pop("derefAlias", None)
if derefAlias:
ldap.set_option(ldap.OPT_DEREF, derefAlias)
try:
result = connection.search_ext_s(**qry)
if not result or len(result) == 0:
- return None, "Entry not found for base='{0}' and filter='{1}'".format(qry['base'], qry['filterstr'])
+ return None, "Entry not found for base='{0}' and filter='{1}'".format(
+ qry["base"], qry["filterstr"]
+ )
if len(result) > 1 and unique_entry:
- if qry.get('scope') == ldap.SCOPE_BASE:
- return None, "multiple entries found matching dn={0}: {1}".format(qry['base'], result)
+ if qry.get("scope") == ldap.SCOPE_BASE:
+ return None, "multiple entries found matching dn={0}: {1}".format(
+ qry["base"], result
+ )
else:
- return None, "multiple entries found matching filter {0}: {1}".format(qry['filterstr'], result)
+ return None, "multiple entries found matching filter {0}: {1}".format(
+ qry["filterstr"], result
+ )
return result, None
except ldap.NO_SUCH_OBJECT:
- return None, "search for entry with base dn='{0}' refers to a non-existent entry".format(qry['base'])
+ return (
+ None,
+ "search for entry with base dn='{0}' refers to a non-existent entry".format(
+ qry["base"]
+ ),
+ )
def openshift_equal_dn_objects(dn_obj, other_dn_obj):
@@ -303,7 +323,9 @@ def openshift_ancestorof_dn(dn, other):
if len(dn_obj) >= len(other_dn_obj):
return False
# Take the last attribute from the other DN to compare against
- return openshift_equal_dn_objects(dn_obj, other_dn_obj[len(other_dn_obj) - len(dn_obj):])
+ return openshift_equal_dn_objects(
+ dn_obj, other_dn_obj[len(other_dn_obj) - len(dn_obj):] # fmt: skip
+ )
class OpenshiftLDAPQueryOnAttribute(object):
@@ -324,33 +346,38 @@ class OpenshiftLDAPQueryOnAttribute(object):
output = []
hex_string = "0123456789abcdef"
for c in buffer:
- if ord(c) > 0x7f or c in ('(', ')', '\\', '*') or c == 0:
+ if ord(c) > 0x7F or c in ("(", ")", "\\", "*") or c == 0:
first = ord(c) >> 4
- second = ord(c) & 0xf
- output += ['\\', hex_string[first], hex_string[second]]
+ second = ord(c) & 0xF
+ output += ["\\", hex_string[first], hex_string[second]]
else:
output.append(c)
- return ''.join(output)
+ return "".join(output)
def build_request(self, ldapuid, attributes):
params = copy.deepcopy(self.qry)
- if self.query_attribute.lower() == 'dn':
+ if self.query_attribute.lower() == "dn":
if ldapuid:
- if not openshift_equal_dn(ldapuid, params['base']) and not openshift_ancestorof_dn(params['base'], ldapuid):
+ if not openshift_equal_dn(
+ ldapuid, params["base"]
+ ) and not openshift_ancestorof_dn(params["base"], ldapuid):
return None, LDAP_SEARCH_OUT_OF_SCOPE_ERROR
- params['base'] = ldapuid
- params['scope'] = ldap.SCOPE_BASE
+ params["base"] = ldapuid
+ params["scope"] = ldap.SCOPE_BASE
# filter that returns all values
- params['filterstr'] = "(objectClass=*)"
- params['attrlist'] = attributes
+ params["filterstr"] = "(objectClass=*)"
+ params["attrlist"] = attributes
else:
# Builds the query containing a filter that conjoins the common filter given
# in the configuration with the specific attribute filter for which the attribute value is given
- specificFilter = "%s=%s" % (self.escape_filter(self.query_attribute), self.escape_filter(ldapuid))
- qry_filter = params.get('filterstr', None)
+ specificFilter = "%s=%s" % (
+ self.escape_filter(self.query_attribute),
+ self.escape_filter(ldapuid),
+ )
+ qry_filter = params.get("filterstr", None)
if qry_filter:
- params['filterstr'] = "(&%s(%s))" % (qry_filter, specificFilter)
- params['attrlist'] = attributes
+ params["filterstr"] = "(&%s(%s))" % (qry_filter, specificFilter)
+ params["attrlist"] = attributes
return params, None
def ldap_search(self, connection, ldapuid, required_attributes, unique_entry=True):
@@ -358,21 +385,29 @@ class OpenshiftLDAPQueryOnAttribute(object):
if error:
return None, error
# set deref alias (TODO: need to set a default value to reset for each transaction)
- derefAlias = query.pop('derefAlias', None)
+ derefAlias = query.pop("derefAlias", None)
if derefAlias:
ldap.set_option(ldap.OPT_DEREF, derefAlias)
try:
result = connection.search_ext_s(**query)
if not result or len(result) == 0:
- return None, "Entry not found for base='{0}' and filter='{1}'".format(query['base'], query['filterstr'])
+ return None, "Entry not found for base='{0}' and filter='{1}'".format(
+ query["base"], query["filterstr"]
+ )
if unique_entry:
if len(result) > 1:
- return None, "Multiple Entries found matching search criteria: %s (%s)" % (query, result)
+ return (
+ None,
+ "Multiple Entries found matching search criteria: %s (%s)"
+ % (query, result),
+ )
result = result[0]
return result, None
except ldap.NO_SUCH_OBJECT:
- return None, "Entry not found for base='{0}' and filter='{1}'".format(query['base'], query['filterstr'])
+ return None, "Entry not found for base='{0}' and filter='{1}'".format(
+ query["base"], query["filterstr"]
+ )
except Exception as err:
return None, "Request %s failed due to: %s" % (query, err)
@@ -384,30 +419,43 @@ class OpenshiftLDAPQuery(object):
def build_request(self, attributes):
params = copy.deepcopy(self.qry)
- params['attrlist'] = attributes
+ params["attrlist"] = attributes
return params
def ldap_search(self, connection, required_attributes):
query = self.build_request(required_attributes)
# set deref alias (TODO: need to set a default value to reset for each transaction)
- derefAlias = query.pop('derefAlias', None)
+ derefAlias = query.pop("derefAlias", None)
if derefAlias:
ldap.set_option(ldap.OPT_DEREF, derefAlias)
try:
result = connection.search_ext_s(**query)
if not result or len(result) == 0:
- return None, "Entry not found for base='{0}' and filter='{1}'".format(query['base'], query['filterstr'])
+ return None, "Entry not found for base='{0}' and filter='{1}'".format(
+ query["base"], query["filterstr"]
+ )
return result, None
except ldap.NO_SUCH_OBJECT:
- return None, "search for entry with base dn='{0}' refers to a non-existent entry".format(query['base'])
+ return (
+ None,
+ "search for entry with base dn='{0}' refers to a non-existent entry".format(
+ query["base"]
+ ),
+ )
class OpenshiftLDAPInterface(object):
-
- def __init__(self, connection, groupQuery, groupNameAttributes, groupMembershipAttributes,
- userQuery, userNameAttributes, config):
-
+ def __init__(
+ self,
+ connection,
+ groupQuery,
+ groupNameAttributes,
+ groupMembershipAttributes,
+ userQuery,
+ userNameAttributes,
+ config,
+ ):
self.connection = connection
self.groupQuery = copy.deepcopy(groupQuery)
self.groupNameAttributes = groupNameAttributes
@@ -416,8 +464,12 @@ class OpenshiftLDAPInterface(object):
self.userNameAttributes = userNameAttributes
self.config = config
- self.tolerate_not_found = boolean(config.get('tolerateMemberNotFoundErrors', False))
- self.tolerate_out_of_scope = boolean(config.get('tolerateMemberOutOfScopeErrors', False))
+ self.tolerate_not_found = boolean(
+ config.get("tolerateMemberNotFoundErrors", False)
+ )
+ self.tolerate_out_of_scope = boolean(
+ config.get("tolerateMemberOutOfScopeErrors", False)
+ )
self.required_group_attributes = [self.groupQuery.query_attribute]
for x in self.groupNameAttributes + self.groupMembershipAttributes:
@@ -434,13 +486,15 @@ class OpenshiftLDAPInterface(object):
def get_group_entry(self, uid):
"""
- get_group_entry returns an LDAP group entry for the given group UID by searching the internal cache
- of the LDAPInterface first, then sending an LDAP query if the cache did not contain the entry.
+ get_group_entry returns an LDAP group entry for the given group UID by searching the internal cache
+ of the LDAPInterface first, then sending an LDAP query if the cache did not contain the entry.
"""
if uid in self.cached_groups:
return self.cached_groups.get(uid), None
- group, err = self.groupQuery.ldap_search(self.connection, uid, self.required_group_attributes)
+ group, err = self.groupQuery.ldap_search(
+ self.connection, uid, self.required_group_attributes
+ )
if err:
return None, err
self.cached_groups[uid] = group
@@ -448,13 +502,15 @@ class OpenshiftLDAPInterface(object):
def get_user_entry(self, uid):
"""
- get_user_entry returns an LDAP group entry for the given user UID by searching the internal cache
- of the LDAPInterface first, then sending an LDAP query if the cache did not contain the entry.
+ get_user_entry returns an LDAP group entry for the given user UID by searching the internal cache
+ of the LDAPInterface first, then sending an LDAP query if the cache did not contain the entry.
"""
if uid in self.cached_users:
return self.cached_users.get(uid), None
- entry, err = self.userQuery.ldap_search(self.connection, uid, self.required_user_attributes)
+ entry, err = self.userQuery.ldap_search(
+ self.connection, uid, self.required_user_attributes
+ )
if err:
return None, err
self.cached_users[uid] = entry
@@ -466,19 +522,19 @@ class OpenshiftLDAPInterface(object):
def list_groups(self):
group_qry = copy.deepcopy(self.groupQuery.qry)
- group_qry['attrlist'] = self.required_group_attributes
+ group_qry["attrlist"] = self.required_group_attributes
groups, err = openshift_ldap_query_for_entries(
- connection=self.connection,
- qry=group_qry,
- unique_entry=False
+ connection=self.connection, qry=group_qry, unique_entry=False
)
if err:
return None, err
group_uids = []
for entry in groups:
- uid = openshift_ldap_get_attribute_for_entry(entry, self.groupQuery.query_attribute)
+ uid = openshift_ldap_get_attribute_for_entry(
+ entry, self.groupQuery.query_attribute
+ )
if not uid:
return None, "Unable to find LDAP group uid for entry %s" % entry
self.cached_groups[uid] = entry
@@ -487,7 +543,7 @@ class OpenshiftLDAPInterface(object):
def extract_members(self, uid):
"""
- returns the LDAP member entries for a group specified with a ldapGroupUID
+ returns the LDAP member entries for a group specified with a ldapGroupUID
"""
# Get group entry from LDAP
group, err = self.get_group_entry(uid)
@@ -514,39 +570,46 @@ class OpenshiftLDAPInterface(object):
class OpenshiftLDAPRFC2307(object):
-
def __init__(self, config, ldap_connection):
-
self.config = config
self.ldap_interface = self.create_ldap_interface(ldap_connection)
def create_ldap_interface(self, connection):
segment = self.config.get("rfc2307")
- groups_base_qry = openshift_ldap_build_base_query(segment['groupsQuery'])
- users_base_qry = openshift_ldap_build_base_query(segment['usersQuery'])
+ groups_base_qry = openshift_ldap_build_base_query(segment["groupsQuery"])
+ users_base_qry = openshift_ldap_build_base_query(segment["usersQuery"])
- groups_query = OpenshiftLDAPQueryOnAttribute(groups_base_qry, segment['groupUIDAttribute'])
- users_query = OpenshiftLDAPQueryOnAttribute(users_base_qry, segment['userUIDAttribute'])
+ groups_query = OpenshiftLDAPQueryOnAttribute(
+ groups_base_qry, segment["groupUIDAttribute"]
+ )
+ users_query = OpenshiftLDAPQueryOnAttribute(
+ users_base_qry, segment["userUIDAttribute"]
+ )
params = dict(
connection=connection,
groupQuery=groups_query,
- groupNameAttributes=segment['groupNameAttributes'],
- groupMembershipAttributes=segment['groupMembershipAttributes'],
+ groupNameAttributes=segment["groupNameAttributes"],
+ groupMembershipAttributes=segment["groupMembershipAttributes"],
userQuery=users_query,
- userNameAttributes=segment['userNameAttributes'],
- config=segment
+ userNameAttributes=segment["userNameAttributes"],
+ config=segment,
)
return OpenshiftLDAPInterface(**params)
def get_username_for_entry(self, entry):
- username = openshift_ldap_get_attribute_for_entry(entry, self.ldap_interface.userNameAttributes)
+ username = openshift_ldap_get_attribute_for_entry(
+ entry, self.ldap_interface.userNameAttributes
+ )
if not username:
- return None, "The user entry (%s) does not map to a OpenShift User name with the given mapping" % entry
+ return (
+ None,
+ "The user entry (%s) does not map to a OpenShift User name with the given mapping"
+ % entry,
+ )
return username, None
def get_group_name_for_uid(self, uid):
-
# Get name from User defined mapping
groupuid_name_mapping = self.config.get("groupUIDNameMapping")
if groupuid_name_mapping and uid in groupuid_name_mapping:
@@ -555,10 +618,13 @@ class OpenshiftLDAPRFC2307(object):
group, err = self.ldap_interface.get_group_entry(uid)
if err:
return None, err
- group_name = openshift_ldap_get_attribute_for_entry(group, self.ldap_interface.groupNameAttributes)
+ group_name = openshift_ldap_get_attribute_for_entry(
+ group, self.ldap_interface.groupNameAttributes
+ )
if not group_name:
- error = "The group entry (%s) does not map to an OpenShift Group name with the given name attribute (%s)" % (
- group, self.ldap_interface.groupNameAttributes
+ error = (
+ "The group entry (%s) does not map to an OpenShift Group name with the given name attribute (%s)"
+ % (group, self.ldap_interface.groupNameAttributes)
)
return None, error
if isinstance(group_name, list):
@@ -570,7 +636,11 @@ class OpenshiftLDAPRFC2307(object):
def is_ldapgroup_exists(self, uid):
group, err = self.ldap_interface.get_group_entry(uid)
if err:
- if err == LDAP_SEARCH_OUT_OF_SCOPE_ERROR or err.startswith("Entry not found") or "non-existent entry" in err:
+ if (
+ err == LDAP_SEARCH_OUT_OF_SCOPE_ERROR
+ or err.startswith("Entry not found")
+ or "non-existent entry" in err
+ ):
return False, None
return False, err
if group:
@@ -585,7 +655,6 @@ class OpenshiftLDAPRFC2307(object):
class OpenshiftLDAP_ADInterface(object):
-
def __init__(self, connection, user_query, group_member_attr, user_name_attr):
self.connection = connection
self.userQuery = user_query
@@ -609,7 +678,9 @@ class OpenshiftLDAP_ADInterface(object):
def populate_cache(self):
if not self.cache_populated:
self.cache_populated = True
- entries, err = self.userQuery.ldap_search(self.connection, self.required_user_attributes)
+ entries, err = self.userQuery.ldap_search(
+ self.connection, self.required_user_attributes
+ )
if err:
return err
@@ -645,7 +716,9 @@ class OpenshiftLDAP_ADInterface(object):
users_in_group = []
for attr in self.groupMembershipAttributes:
query_on_attribute = OpenshiftLDAPQueryOnAttribute(self.userQuery.qry, attr)
- entries, error = query_on_attribute.ldap_search(self.connection, uid, self.required_user_attributes, unique_entry=False)
+ entries, error = query_on_attribute.ldap_search(
+ self.connection, uid, self.required_user_attributes, unique_entry=False
+ )
if error and "not found" not in error:
return None, error
if not entries:
@@ -660,15 +733,13 @@ class OpenshiftLDAP_ADInterface(object):
class OpenshiftLDAPActiveDirectory(object):
-
def __init__(self, config, ldap_connection):
-
self.config = config
self.ldap_interface = self.create_ldap_interface(ldap_connection)
def create_ldap_interface(self, connection):
segment = self.config.get("activeDirectory")
- base_query = openshift_ldap_build_base_query(segment['usersQuery'])
+ base_query = openshift_ldap_build_base_query(segment["usersQuery"])
user_query = OpenshiftLDAPQuery(base_query)
return OpenshiftLDAP_ADInterface(
@@ -679,9 +750,15 @@ class OpenshiftLDAPActiveDirectory(object):
)
def get_username_for_entry(self, entry):
- username = openshift_ldap_get_attribute_for_entry(entry, self.ldap_interface.userNameAttributes)
+ username = openshift_ldap_get_attribute_for_entry(
+ entry, self.ldap_interface.userNameAttributes
+ )
if not username:
- return None, "The user entry (%s) does not map to a OpenShift User name with the given mapping" % entry
+ return (
+ None,
+ "The user entry (%s) does not map to a OpenShift User name with the given mapping"
+ % entry,
+ )
return username, None
def get_group_name_for_uid(self, uid):
@@ -702,8 +779,15 @@ class OpenshiftLDAPActiveDirectory(object):
class OpenshiftLDAP_AugmentedADInterface(OpenshiftLDAP_ADInterface):
-
- def __init__(self, connection, user_query, group_member_attr, user_name_attr, group_qry, group_name_attr):
+ def __init__(
+ self,
+ connection,
+ user_query,
+ group_member_attr,
+ user_name_attr,
+ group_qry,
+ group_name_attr,
+ ):
super(OpenshiftLDAP_AugmentedADInterface, self).__init__(
connection, user_query, group_member_attr, user_name_attr
)
@@ -719,13 +803,15 @@ class OpenshiftLDAP_AugmentedADInterface(OpenshiftLDAP_ADInterface):
def get_group_entry(self, uid):
"""
- get_group_entry returns an LDAP group entry for the given group UID by searching the internal cache
- of the LDAPInterface first, then sending an LDAP query if the cache did not contain the entry.
+ get_group_entry returns an LDAP group entry for the given group UID by searching the internal cache
+ of the LDAPInterface first, then sending an LDAP query if the cache did not contain the entry.
"""
if uid in self.cached_groups:
return self.cached_groups.get(uid), None
- group, err = self.groupQuery.ldap_search(self.connection, uid, self.required_group_attributes)
+ group, err = self.groupQuery.ldap_search(
+ self.connection, uid, self.required_group_attributes
+ )
if err:
return None, err
self.cached_groups[uid] = group
@@ -750,19 +836,19 @@ class OpenshiftLDAP_AugmentedADInterface(OpenshiftLDAP_ADInterface):
class OpenshiftLDAPAugmentedActiveDirectory(OpenshiftLDAPRFC2307):
-
def __init__(self, config, ldap_connection):
-
self.config = config
self.ldap_interface = self.create_ldap_interface(ldap_connection)
def create_ldap_interface(self, connection):
segment = self.config.get("augmentedActiveDirectory")
- user_base_query = openshift_ldap_build_base_query(segment['usersQuery'])
- groups_base_qry = openshift_ldap_build_base_query(segment['groupsQuery'])
+ user_base_query = openshift_ldap_build_base_query(segment["usersQuery"])
+ groups_base_qry = openshift_ldap_build_base_query(segment["groupsQuery"])
user_query = OpenshiftLDAPQuery(user_base_query)
- groups_query = OpenshiftLDAPQueryOnAttribute(groups_base_qry, segment['groupUIDAttribute'])
+ groups_query = OpenshiftLDAPQueryOnAttribute(
+ groups_base_qry, segment["groupUIDAttribute"]
+ )
return OpenshiftLDAP_AugmentedADInterface(
connection=connection,
@@ -770,7 +856,7 @@ class OpenshiftLDAPAugmentedActiveDirectory(OpenshiftLDAPRFC2307):
group_member_attr=segment["groupMembershipAttributes"],
user_name_attr=segment["userNameAttributes"],
group_qry=groups_query,
- group_name_attr=segment["groupNameAttributes"]
+ group_name_attr=segment["groupNameAttributes"],
)
def is_ldapgroup_exists(self, uid):
diff --git a/plugins/module_utils/openshift_process.py b/plugins/module_utils/openshift_process.py
index 6fa69d1..3996aed 100644
--- a/plugins/module_utils/openshift_process.py
+++ b/plugins/module_utils/openshift_process.py
@@ -1,15 +1,16 @@
#!/usr/bin/env python
-from __future__ import (absolute_import, division, print_function)
+from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
import os
-import traceback
from ansible.module_utils._text import to_native
-
-from ansible_collections.community.okd.plugins.module_utils.openshift_common import AnsibleOpenshiftModule
+from ansible_collections.community.okd.plugins.module_utils.openshift_common import (
+ AnsibleOpenshiftModule,
+)
try:
from kubernetes.dynamic.exceptions import DynamicApiError
@@ -124,7 +125,6 @@ class OpenShiftProcess(AnsibleOpenshiftModule):
self.exit_json(**result)
def create_resources(self, definitions):
-
params = {"namespace": self.params.get("namespace_target")}
self.params["apply"] = False
@@ -139,9 +139,7 @@ class OpenShiftProcess(AnsibleOpenshiftModule):
continue
kind = definition.get("kind")
if kind and kind.endswith("List"):
- flattened_definitions.extend(
- self.flatten_list_kind(definition, params)
- )
+ flattened_definitions.extend(self.flatten_list_kind(definition, params))
else:
flattened_definitions.append(self.merge_params(definition, params))
diff --git a/plugins/module_utils/openshift_registry.py b/plugins/module_utils/openshift_registry.py
index 32a1830..557a7d1 100644
--- a/plugins/module_utils/openshift_registry.py
+++ b/plugins/module_utils/openshift_registry.py
@@ -1,12 +1,15 @@
#!/usr/bin/env python
-from __future__ import (absolute_import, division, print_function)
+from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
import traceback
from urllib.parse import urlparse
-from ansible_collections.community.okd.plugins.module_utils.openshift_common import AnsibleOpenshiftModule
+from ansible_collections.community.okd.plugins.module_utils.openshift_common import (
+ AnsibleOpenshiftModule,
+)
from ansible_collections.community.okd.plugins.module_utils.openshift_docker_image import (
parse_docker_image_ref,
@@ -15,6 +18,7 @@ from ansible_collections.community.okd.plugins.module_utils.openshift_docker_ima
try:
from requests import request
from requests.auth import HTTPBasicAuth
+
HAS_REQUESTS_MODULE = True
requests_import_exception = None
except ImportError as e:
@@ -32,11 +36,7 @@ class OpenShiftRegistry(AnsibleOpenshiftModule):
kind = "ImageStream"
api_version = "image.openshift.io/v1"
- params = dict(
- kind=kind,
- api_version=api_version,
- namespace=namespace
- )
+ params = dict(kind=kind, api_version=api_version, namespace=namespace)
result = self.kubernetes_facts(**params)
imagestream = []
if len(result["resources"]) > 0:
@@ -44,7 +44,6 @@ class OpenShiftRegistry(AnsibleOpenshiftModule):
return imagestream
def find_registry_info(self):
-
def _determine_registry(image_stream):
public, internal = None, None
docker_repo = image_stream["status"].get("publicDockerImageRepository")
@@ -72,39 +71,46 @@ class OpenShiftRegistry(AnsibleOpenshiftModule):
self.fail_json(msg="The integrated registry has not been configured")
return internal, public
- self.fail_json(msg="No Image Streams could be located to retrieve registry info.")
+ self.fail_json(
+ msg="No Image Streams could be located to retrieve registry info."
+ )
def execute_module(self):
result = {}
- result["internal_hostname"], result["public_hostname"] = self.find_registry_info()
+ (
+ result["internal_hostname"],
+ result["public_hostname"],
+ ) = self.find_registry_info()
if self.check:
public_registry = result["public_hostname"]
if not public_registry:
result["check"] = dict(
- reached=False,
- msg="Registry does not have a public hostname."
+ reached=False, msg="Registry does not have a public hostname."
)
else:
- headers = {
- 'Content-Type': 'application/json'
- }
- params = {
- 'method': 'GET',
- 'verify': False
- }
+ headers = {"Content-Type": "application/json"}
+ params = {"method": "GET", "verify": False}
if self.client.configuration.api_key:
headers.update(self.client.configuration.api_key)
- elif self.client.configuration.username and self.client.configuration.password:
+ elif (
+ self.client.configuration.username
+ and self.client.configuration.password
+ ):
if not HAS_REQUESTS_MODULE:
result["check"] = dict(
reached=False,
msg="The requests python package is missing, try `pip install requests`",
- error=requests_import_exception
+ error=requests_import_exception,
)
self.exit_json(**result)
params.update(
- dict(auth=HTTPBasicAuth(self.client.configuration.username, self.client.configuration.password))
+ dict(
+ auth=HTTPBasicAuth(
+ self.client.configuration.username,
+ self.client.configuration.password,
+ )
+ )
)
# verify ssl
@@ -112,23 +118,20 @@ class OpenShiftRegistry(AnsibleOpenshiftModule):
if len(host.scheme) == 0:
registry_url = "https://" + public_registry
- if registry_url.startswith("https://") and self.client.configuration.ssl_ca_cert:
- params.update(
- dict(verify=self.client.configuration.ssl_ca_cert)
- )
- params.update(
- dict(headers=headers)
- )
+ if (
+ registry_url.startswith("https://")
+ and self.client.configuration.ssl_ca_cert
+ ):
+ params.update(dict(verify=self.client.configuration.ssl_ca_cert))
+ params.update(dict(headers=headers))
last_bad_status, last_bad_reason = None, None
for path in ("/", "/healthz"):
- params.update(
- dict(url=registry_url + path)
- )
+ params.update(dict(url=registry_url + path))
response = request(**params)
if response.status_code == 200:
result["check"] = dict(
reached=True,
- msg="The local client can contact the integrated registry."
+ msg="The local client can contact the integrated registry.",
)
self.exit_json(**result)
last_bad_reason = response.reason
@@ -136,9 +139,8 @@ class OpenShiftRegistry(AnsibleOpenshiftModule):
result["check"] = dict(
reached=False,
- msg="Unable to contact the integrated registry using local client. Status=%d, Reason=%s" % (
- last_bad_status, last_bad_reason
- )
+ msg="Unable to contact the integrated registry using local client. Status=%d, Reason=%s"
+ % (last_bad_status, last_bad_reason),
)
self.exit_json(**result)
diff --git a/plugins/modules/k8s.py b/plugins/modules/k8s.py
index c3b8d1b..ae3a9b4 100644
--- a/plugins/modules/k8s.py
+++ b/plugins/modules/k8s.py
@@ -10,7 +10,7 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type
# STARTREMOVE (downstream)
-DOCUMENTATION = r'''
+DOCUMENTATION = r"""
module: k8s
@@ -142,9 +142,9 @@ requirements:
- "python >= 3.6"
- "kubernetes >= 12.0.0"
- "PyYAML >= 3.11"
-'''
+"""
-EXAMPLES = r'''
+EXAMPLES = r"""
- name: Create a k8s namespace
community.okd.k8s:
name: testing
@@ -169,10 +169,10 @@ EXAMPLES = r'''
app: galaxy
service: web
ports:
- - protocol: TCP
- targetPort: 8000
- name: port-8000-tcp
- port: 8000
+ - protocol: TCP
+ targetPort: 8000
+ name: port-8000-tcp
+ port: 8000
- name: Remove an existing Service object
community.okd.k8s:
@@ -206,18 +206,18 @@ EXAMPLES = r'''
state: present
definition: "{{ lookup('template', '/testing/deployment.yml') | from_yaml }}"
validate:
- fail_on_error: yes
+ fail_on_error: true
- name: warn on validation errors, check for unexpected properties
community.okd.k8s:
state: present
definition: "{{ lookup('template', '/testing/deployment.yml') | from_yaml }}"
validate:
- fail_on_error: no
- strict: yes
-'''
+ fail_on_error: false
+ strict: true
+"""
-RETURN = r'''
+RETURN = r"""
result:
description:
- The created, patched, or otherwise present object. Will be empty in the case of a deletion.
@@ -254,22 +254,26 @@ result:
type: int
sample: 48
error:
- description: error while trying to create/delete the object.
+ description: Error while trying to create/delete the object.
returned: error
type: complex
-'''
+"""
# ENDREMOVE (downstream)
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
- NAME_ARG_SPEC, RESOURCE_ARG_SPEC, AUTH_ARG_SPEC, WAIT_ARG_SPEC, DELETE_OPTS_ARG_SPEC
+ NAME_ARG_SPEC,
+ RESOURCE_ARG_SPEC,
+ AUTH_ARG_SPEC,
+ WAIT_ARG_SPEC,
+ DELETE_OPTS_ARG_SPEC,
)
def validate_spec():
return dict(
- fail_on_error=dict(type='bool'),
+ fail_on_error=dict(type="bool"),
version=dict(),
- strict=dict(type='bool', default=True)
+ strict=dict(type="bool", default=True),
)
@@ -279,30 +283,41 @@ def argspec():
argument_spec.update(RESOURCE_ARG_SPEC)
argument_spec.update(AUTH_ARG_SPEC)
argument_spec.update(WAIT_ARG_SPEC)
- argument_spec['merge_type'] = dict(type='list', elements='str', choices=['json', 'merge', 'strategic-merge'])
- argument_spec['validate'] = dict(type='dict', default=None, options=validate_spec())
- argument_spec['append_hash'] = dict(type='bool', default=False)
- argument_spec['apply'] = dict(type='bool', default=False)
- argument_spec['template'] = dict(type='raw', default=None)
- argument_spec['delete_options'] = dict(type='dict', default=None, options=DELETE_OPTS_ARG_SPEC)
- argument_spec['continue_on_error'] = dict(type='bool', default=False)
- argument_spec['state'] = dict(default='present', choices=['present', 'absent', 'patched'])
- argument_spec['force'] = dict(type='bool', default=False)
+ argument_spec["merge_type"] = dict(
+ type="list", elements="str", choices=["json", "merge", "strategic-merge"]
+ )
+ argument_spec["validate"] = dict(type="dict", default=None, options=validate_spec())
+ argument_spec["append_hash"] = dict(type="bool", default=False)
+ argument_spec["apply"] = dict(type="bool", default=False)
+ argument_spec["template"] = dict(type="raw", default=None)
+ argument_spec["delete_options"] = dict(
+ type="dict", default=None, options=DELETE_OPTS_ARG_SPEC
+ )
+ argument_spec["continue_on_error"] = dict(type="bool", default=False)
+ argument_spec["state"] = dict(
+ default="present", choices=["present", "absent", "patched"]
+ )
+ argument_spec["force"] = dict(type="bool", default=False)
return argument_spec
def main():
mutually_exclusive = [
- ('resource_definition', 'src'),
- ('merge_type', 'apply'),
- ('template', 'resource_definition'),
- ('template', 'src'),
+ ("resource_definition", "src"),
+ ("merge_type", "apply"),
+ ("template", "resource_definition"),
+ ("template", "src"),
]
from ansible_collections.community.okd.plugins.module_utils.k8s import OKDRawModule
- module = OKDRawModule(argument_spec=argspec(), supports_check_mode=True, mutually_exclusive=mutually_exclusive)
+
+ module = OKDRawModule(
+ argument_spec=argspec(),
+ supports_check_mode=True,
+ mutually_exclusive=mutually_exclusive,
+ )
module.run_module()
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/plugins/modules/openshift_adm_groups_sync.py b/plugins/modules/openshift_adm_groups_sync.py
index 66b0fbb..3f5f14b 100644
--- a/plugins/modules/openshift_adm_groups_sync.py
+++ b/plugins/modules/openshift_adm_groups_sync.py
@@ -96,31 +96,31 @@ EXAMPLES = r"""
- name: Sync all groups from an LDAP server
openshift_adm_groups_sync:
src:
- kind: LDAPSyncConfig
- apiVersion: v1
- url: ldap://localhost:1390
- insecure: true
- bindDN: cn=admin,dc=example,dc=org
- bindPassword: adminpassword
- rfc2307:
- groupsQuery:
- baseDN: "cn=admins,ou=groups,dc=example,dc=org"
- scope: sub
- derefAliases: never
- filter: (objectClass=*)
- pageSize: 0
- groupUIDAttribute: dn
- groupNameAttributes: [ cn ]
- groupMembershipAttributes: [ member ]
- usersQuery:
- baseDN: "ou=users,dc=example,dc=org"
- scope: sub
- derefAliases: never
- pageSize: 0
- userUIDAttribute: dn
- userNameAttributes: [ mail ]
- tolerateMemberNotFoundErrors: true
- tolerateMemberOutOfScopeErrors: true
+ kind: LDAPSyncConfig
+ apiVersion: v1
+ url: ldap://localhost:1390
+ insecure: true
+ bindDN: cn=admin,dc=example,dc=org
+ bindPassword: adminpassword
+ rfc2307:
+ groupsQuery:
+ baseDN: "cn=admins,ou=groups,dc=example,dc=org"
+ scope: sub
+ derefAliases: never
+ filter: (objectClass=*)
+ pageSize: 0
+ groupUIDAttribute: dn
+ groupNameAttributes: [cn]
+ groupMembershipAttributes: [member]
+ usersQuery:
+ baseDN: "ou=users,dc=example,dc=org"
+ scope: sub
+ derefAliases: never
+ pageSize: 0
+ userUIDAttribute: dn
+ userNameAttributes: [mail]
+ tolerateMemberNotFoundErrors: true
+ tolerateMemberOutOfScopeErrors: true
# Sync all groups except the ones from the deny_groups from an LDAP server
- name: Sync all groups from an LDAP server using deny_groups
@@ -192,20 +192,21 @@ builds:
# ENDREMOVE (downstream)
import copy
-import traceback
-from ansible_collections.kubernetes.core.plugins.module_utils.args_common import AUTH_ARG_SPEC
+from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
+ AUTH_ARG_SPEC,
+)
def argument_spec():
args = copy.deepcopy(AUTH_ARG_SPEC)
args.update(
dict(
- state=dict(type='str', choices=['absent', 'present'], default='present'),
- type=dict(type='str', choices=['ldap', 'openshift'], default='ldap'),
- sync_config=dict(type='dict', aliases=['config', 'src'], required=True),
- deny_groups=dict(type='list', elements='str', default=[]),
- allow_groups=dict(type='list', elements='str', default=[]),
+ state=dict(type="str", choices=["absent", "present"], default="present"),
+ type=dict(type="str", choices=["ldap", "openshift"], default="ldap"),
+ sync_config=dict(type="dict", aliases=["config", "src"], required=True),
+ deny_groups=dict(type="list", elements="str", default=[]),
+ allow_groups=dict(type="list", elements="str", default=[]),
)
)
return args
@@ -213,12 +214,14 @@ def argument_spec():
def main():
from ansible_collections.community.okd.plugins.module_utils.openshift_groups import (
- OpenshiftGroupsSync
+ OpenshiftGroupsSync,
)
- module = OpenshiftGroupsSync(argument_spec=argument_spec(), supports_check_mode=True)
+ module = OpenshiftGroupsSync(
+ argument_spec=argument_spec(), supports_check_mode=True
+ )
module.run_module()
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/plugins/modules/openshift_adm_migrate_template_instances.py b/plugins/modules/openshift_adm_migrate_template_instances.py
index 05d5563..ba3039d 100644
--- a/plugins/modules/openshift_adm_migrate_template_instances.py
+++ b/plugins/modules/openshift_adm_migrate_template_instances.py
@@ -31,14 +31,14 @@ requirements:
"""
EXAMPLES = r"""
- - name: Migrate TemplateInstances in namespace=test
- community.okd.openshift_adm_migrate_template_instances:
- namespace: test
- register: _result
+- name: Migrate TemplateInstances in namespace=test
+ community.okd.openshift_adm_migrate_template_instances:
+ namespace: test
+ register: _result
- - name: Migrate TemplateInstances in all namespaces
- community.okd.openshift_adm_migrate_template_instances:
- register: _result
+- name: Migrate TemplateInstances in all namespaces
+ community.okd.openshift_adm_migrate_template_instances:
+ register: _result
"""
RETURN = r"""
@@ -235,7 +235,9 @@ result:
from ansible.module_utils._text import to_native
-from ansible_collections.community.okd.plugins.module_utils.openshift_common import AnsibleOpenshiftModule
+from ansible_collections.community.okd.plugins.module_utils.openshift_common import (
+ AnsibleOpenshiftModule,
+)
try:
from kubernetes.dynamic.exceptions import DynamicApiError
@@ -339,9 +341,7 @@ class OpenShiftMigrateTemplateInstances(AnsibleOpenshiftModule):
if ti_to_be_migrated:
if self.check_mode:
- self.exit_json(
- **{"changed": True, "result": ti_to_be_migrated}
- )
+ self.exit_json(**{"changed": True, "result": ti_to_be_migrated})
else:
for ti_elem in ti_to_be_migrated:
results["result"].append(
@@ -363,7 +363,9 @@ def argspec():
def main():
argument_spec = argspec()
- module = OpenShiftMigrateTemplateInstances(argument_spec=argument_spec, supports_check_mode=True)
+ module = OpenShiftMigrateTemplateInstances(
+ argument_spec=argument_spec, supports_check_mode=True
+ )
module.run_module()
diff --git a/plugins/modules/openshift_adm_prune_auth.py b/plugins/modules/openshift_adm_prune_auth.py
index a9833fa..fe0aec2 100644
--- a/plugins/modules/openshift_adm_prune_auth.py
+++ b/plugins/modules/openshift_adm_prune_auth.py
@@ -5,10 +5,11 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
# STARTREMOVE (downstream)
-DOCUMENTATION = r'''
+DOCUMENTATION = r"""
module: openshift_adm_prune_auth
@@ -58,9 +59,9 @@ options:
requirements:
- python >= 3.6
- kubernetes >= 12.0.0
-'''
+"""
-EXAMPLES = r'''
+EXAMPLES = r"""
- name: Prune all roles from default namespace
openshift_adm_prune_auth:
resource: roles
@@ -72,10 +73,10 @@ EXAMPLES = r'''
namespace: testing
label_selectors:
- phase=production
-'''
+"""
-RETURN = r'''
+RETURN = r"""
cluster_role_binding:
type: list
description: list of cluster role binding deleted.
@@ -96,37 +97,45 @@ group:
type: list
description: list of Security Context Constraints deleted.
returned: I(resource=users)
-'''
+"""
# ENDREMOVE (downstream)
import copy
-from ansible_collections.kubernetes.core.plugins.module_utils.args_common import AUTH_ARG_SPEC
+from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
+ AUTH_ARG_SPEC,
+)
def argument_spec():
args = copy.deepcopy(AUTH_ARG_SPEC)
args.update(
dict(
- resource=dict(type='str', required=True, choices=['roles', 'clusterroles', 'users', 'groups']),
- namespace=dict(type='str'),
- name=dict(type='str'),
- label_selectors=dict(type='list', elements='str'),
+ resource=dict(
+ type="str",
+ required=True,
+ choices=["roles", "clusterroles", "users", "groups"],
+ ),
+ namespace=dict(type="str"),
+ name=dict(type="str"),
+ label_selectors=dict(type="list", elements="str"),
)
)
return args
def main():
-
from ansible_collections.community.okd.plugins.module_utils.openshift_adm_prune_auth import (
- OpenShiftAdmPruneAuth)
+ OpenShiftAdmPruneAuth,
+ )
- module = OpenShiftAdmPruneAuth(argument_spec=argument_spec(),
- mutually_exclusive=[("name", "label_selectors")],
- supports_check_mode=True)
+ module = OpenShiftAdmPruneAuth(
+ argument_spec=argument_spec(),
+ mutually_exclusive=[("name", "label_selectors")],
+ supports_check_mode=True,
+ )
module.run_module()
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/plugins/modules/openshift_adm_prune_builds.py b/plugins/modules/openshift_adm_prune_builds.py
index b0b831e..ffc86f1 100644
--- a/plugins/modules/openshift_adm_prune_builds.py
+++ b/plugins/modules/openshift_adm_prune_builds.py
@@ -5,10 +5,11 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
# STARTREMOVE (downstream)
-DOCUMENTATION = r'''
+DOCUMENTATION = r"""
module: openshift_adm_prune_builds
@@ -45,14 +46,14 @@ options:
requirements:
- python >= 3.6
- kubernetes >= 12.0.0
-'''
+"""
-EXAMPLES = r'''
+EXAMPLES = r"""
# Run deleting older completed and failed builds and also including
# all builds whose associated BuildConfig no longer exists
- name: Run delete orphan Builds
community.okd.openshift_adm_prune_builds:
- orphans: True
+ orphans: true
# Run deleting older completed and failed builds keep younger than 2hours
- name: Run delete builds, keep younger than 2h
@@ -63,9 +64,9 @@ EXAMPLES = r'''
- name: Run delete builds from namespace
community.okd.openshift_adm_prune_builds:
namespace: testing_namespace
-'''
+"""
-RETURN = r'''
+RETURN = r"""
builds:
description:
- The builds that were deleted
@@ -92,33 +93,38 @@ builds:
description: Current status details for the object.
returned: success
type: dict
-'''
+"""
# ENDREMOVE (downstream)
import copy
-from ansible_collections.kubernetes.core.plugins.module_utils.args_common import AUTH_ARG_SPEC
+from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
+ AUTH_ARG_SPEC,
+)
def argument_spec():
args = copy.deepcopy(AUTH_ARG_SPEC)
args.update(
dict(
- namespace=dict(type='str'),
- keep_younger_than=dict(type='int'),
- orphans=dict(type='bool', default=False),
+ namespace=dict(type="str"),
+ keep_younger_than=dict(type="int"),
+ orphans=dict(type="bool", default=False),
)
)
return args
def main():
+ from ansible_collections.community.okd.plugins.module_utils.openshift_builds import (
+ OpenShiftPruneBuilds,
+ )
- from ansible_collections.community.okd.plugins.module_utils.openshift_builds import OpenShiftPruneBuilds
-
- module = OpenShiftPruneBuilds(argument_spec=argument_spec(), supports_check_mode=True)
+ module = OpenShiftPruneBuilds(
+ argument_spec=argument_spec(), supports_check_mode=True
+ )
module.run_module()
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/plugins/modules/openshift_adm_prune_deployments.py b/plugins/modules/openshift_adm_prune_deployments.py
index bdef184..963e3c9 100644
--- a/plugins/modules/openshift_adm_prune_deployments.py
+++ b/plugins/modules/openshift_adm_prune_deployments.py
@@ -5,10 +5,11 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
# STARTREMOVE (downstream)
-DOCUMENTATION = r'''
+DOCUMENTATION = r"""
module: openshift_adm_prune_deployments
@@ -45,32 +46,34 @@ options:
requirements:
- python >= 3.6
- kubernetes >= 12.0.0
-'''
+"""
-EXAMPLES = r'''
+EXAMPLES = r"""
- name: Prune Deployments from testing namespace
community.okd.openshift_adm_prune_deployments:
namespace: testing
- name: Prune orphans deployments, keep younger than 2hours
community.okd.openshift_adm_prune_deployments:
- orphans: True
+ orphans: true
keep_younger_than: 120
-'''
+"""
-RETURN = r'''
+RETURN = r"""
replication_controllers:
type: list
description: list of replication controllers candidate for pruning.
returned: always
-'''
+"""
# ENDREMOVE (downstream)
import copy
try:
- from ansible_collections.kubernetes.core.plugins.module_utils.args_common import AUTH_ARG_SPEC
+ from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
+ AUTH_ARG_SPEC,
+ )
except ImportError as e:
pass
@@ -79,22 +82,28 @@ def argument_spec():
args = copy.deepcopy(AUTH_ARG_SPEC)
args.update(
dict(
- namespace=dict(type='str',),
- keep_younger_than=dict(type='int',),
- orphans=dict(type='bool', default=False),
+ namespace=dict(
+ type="str",
+ ),
+ keep_younger_than=dict(
+ type="int",
+ ),
+ orphans=dict(type="bool", default=False),
)
)
return args
def main():
-
from ansible_collections.community.okd.plugins.module_utils.openshift_adm_prune_deployments import (
- OpenShiftAdmPruneDeployment)
+ OpenShiftAdmPruneDeployment,
+ )
- module = OpenShiftAdmPruneDeployment(argument_spec=argument_spec(), supports_check_mode=True)
+ module = OpenShiftAdmPruneDeployment(
+ argument_spec=argument_spec(), supports_check_mode=True
+ )
module.run_module()
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/plugins/modules/openshift_adm_prune_images.py b/plugins/modules/openshift_adm_prune_images.py
index d470fa8..41bd5c4 100644
--- a/plugins/modules/openshift_adm_prune_images.py
+++ b/plugins/modules/openshift_adm_prune_images.py
@@ -5,10 +5,11 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
# STARTREMOVE (downstream)
-DOCUMENTATION = r'''
+DOCUMENTATION = r"""
module: openshift_adm_prune_images
@@ -84,9 +85,9 @@ requirements:
- python >= 3.6
- kubernetes >= 12.0.0
- docker-image-py
-'''
+"""
-EXAMPLES = r'''
+EXAMPLES = r"""
# Prune if only images and their referrers were more than an hour old
- name: Prune image with referrer been more than an hour old
community.okd.openshift_adm_prune_images:
@@ -102,10 +103,10 @@ EXAMPLES = r'''
community.okd.openshift_adm_prune_images:
registry_url: http://registry.example.org
registry_validate_certs: false
-'''
+"""
-RETURN = r'''
+RETURN = r"""
updated_image_streams:
description:
- The images streams updated.
@@ -275,41 +276,44 @@ deleted_images:
},
...
]
-'''
+"""
# ENDREMOVE (downstream)
import copy
-from ansible_collections.kubernetes.core.plugins.module_utils.args_common import AUTH_ARG_SPEC
+from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
+ AUTH_ARG_SPEC,
+)
def argument_spec():
args = copy.deepcopy(AUTH_ARG_SPEC)
args.update(
dict(
- namespace=dict(type='str'),
- all_images=dict(type='bool', default=True),
- keep_younger_than=dict(type='int'),
- prune_over_size_limit=dict(type='bool', default=False),
- registry_url=dict(type='str'),
- registry_validate_certs=dict(type='bool'),
- registry_ca_cert=dict(type='path'),
- prune_registry=dict(type='bool', default=True),
- ignore_invalid_refs=dict(type='bool', default=False),
+ namespace=dict(type="str"),
+ all_images=dict(type="bool", default=True),
+ keep_younger_than=dict(type="int"),
+ prune_over_size_limit=dict(type="bool", default=False),
+ registry_url=dict(type="str"),
+ registry_validate_certs=dict(type="bool"),
+ registry_ca_cert=dict(type="path"),
+ prune_registry=dict(type="bool", default=True),
+ ignore_invalid_refs=dict(type="bool", default=False),
)
)
return args
def main():
-
from ansible_collections.community.okd.plugins.module_utils.openshift_adm_prune_images import (
- OpenShiftAdmPruneImages
+ OpenShiftAdmPruneImages,
)
- module = OpenShiftAdmPruneImages(argument_spec=argument_spec(), supports_check_mode=True)
+ module = OpenShiftAdmPruneImages(
+ argument_spec=argument_spec(), supports_check_mode=True
+ )
module.run_module()
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/plugins/modules/openshift_auth.py b/plugins/modules/openshift_auth.py
index 422018c..4fdb169 100644
--- a/plugins/modules/openshift_auth.py
+++ b/plugins/modules/openshift_auth.py
@@ -5,9 +5,10 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
-DOCUMENTATION = r'''
+DOCUMENTATION = r"""
module: openshift_auth
@@ -74,46 +75,49 @@ requirements:
- urllib3
- requests
- requests-oauthlib
-'''
+"""
-EXAMPLES = r'''
-- hosts: localhost
+EXAMPLES = r"""
+- name: Example Playbook
+ hosts: localhost
module_defaults:
group/community.okd.okd:
host: https://k8s.example.com/
ca_cert: ca.pem
tasks:
- - block:
- # It's good practice to store login credentials in a secure vault and not
- # directly in playbooks.
- - include_vars: openshift_passwords.yml
+ - name: Authenticate to OpenShift cluster and gell a list of all pods from any namespace
+ block:
+ # It's good practice to store login credentials in a secure vault and not
+ # directly in playbooks.
+ - name: Include 'openshift_passwords.yml'
+ ansible.builtin.include_vars: openshift_passwords.yml
- - name: Log in (obtain access token)
- community.okd.openshift_auth:
- username: admin
- password: "{{ openshift_admin_password }}"
- register: openshift_auth_results
+ - name: Log in (obtain access token)
+ community.okd.openshift_auth:
+ username: admin
+ password: "{{ openshift_admin_password }}"
+ register: openshift_auth_results
- # Previous task provides the token/api_key, while all other parameters
- # are taken from module_defaults
- - name: Get a list of all pods from any namespace
- kubernetes.core.k8s_info:
- api_key: "{{ openshift_auth_results.openshift_auth.api_key }}"
- kind: Pod
- register: pod_list
+ # Previous task provides the token/api_key, while all other parameters
+ # are taken from module_defaults
+ - name: Get a list of all pods from any namespace
+ kubernetes.core.k8s_info:
+ api_key: "{{ openshift_auth_results.openshift_auth.api_key }}"
+ kind: Pod
+ register: pod_list
- always:
- - name: If login succeeded, try to log out (revoke access token)
- when: openshift_auth_results.openshift_auth.api_key is defined
- community.okd.openshift_auth:
- state: absent
- api_key: "{{ openshift_auth_results.openshift_auth.api_key }}"
-'''
+ always:
+ - name: If login succeeded, try to log out (revoke access token)
+ when: openshift_auth_results.openshift_auth.api_key is defined
+ community.okd.openshift_auth:
+ state: absent
+ api_key: "{{ openshift_auth_results.openshift_auth.api_key }}"
+"""
# Returned value names need to match k8s modules parameter names, to make it
# easy to pass returned values of openshift_auth to other k8s modules.
# Discussion: https://github.com/ansible/ansible/pull/50807#discussion_r248827899
-RETURN = r'''
+RETURN = r"""
openshift_auth:
description: OpenShift authentication facts.
returned: success
@@ -164,7 +168,7 @@ k8s_auth:
description: Username for authenticating with the API server.
returned: success
type: str
-'''
+"""
import traceback
@@ -179,52 +183,52 @@ import hashlib
# 3rd party imports
try:
import requests
+
HAS_REQUESTS = True
except ImportError:
HAS_REQUESTS = False
try:
from requests_oauthlib import OAuth2Session
+
HAS_REQUESTS_OAUTH = True
except ImportError:
HAS_REQUESTS_OAUTH = False
try:
from urllib3.util import make_headers
+
HAS_URLLIB3 = True
except ImportError:
HAS_URLLIB3 = False
K8S_AUTH_ARG_SPEC = {
- 'state': {
- 'default': 'present',
- 'choices': ['present', 'absent'],
+ "state": {
+ "default": "present",
+ "choices": ["present", "absent"],
},
- 'host': {'required': True},
- 'username': {},
- 'password': {'no_log': True},
- 'ca_cert': {'type': 'path', 'aliases': ['ssl_ca_cert']},
- 'validate_certs': {
- 'type': 'bool',
- 'default': True,
- 'aliases': ['verify_ssl']
- },
- 'api_key': {'no_log': True},
+ "host": {"required": True},
+ "username": {},
+ "password": {"no_log": True},
+ "ca_cert": {"type": "path", "aliases": ["ssl_ca_cert"]},
+ "validate_certs": {"type": "bool", "default": True, "aliases": ["verify_ssl"]},
+ "api_key": {"no_log": True},
}
def get_oauthaccesstoken_objectname_from_token(token_name):
-
"""
- openshift convert the access token to an OAuthAccessToken resource name using the algorithm
- https://github.com/openshift/console/blob/9f352ba49f82ad693a72d0d35709961428b43b93/pkg/server/server.go#L609-L613
+ openshift convert the access token to an OAuthAccessToken resource name using the algorithm
+ https://github.com/openshift/console/blob/9f352ba49f82ad693a72d0d35709961428b43b93/pkg/server/server.go#L609-L613
"""
sha256Prefix = "sha256~"
content = token_name.strip(sha256Prefix)
- b64encoded = urlsafe_b64encode(hashlib.sha256(content.encode()).digest()).rstrip(b'=')
+ b64encoded = urlsafe_b64encode(hashlib.sha256(content.encode()).digest()).rstrip(
+ b"="
+ )
return sha256Prefix + b64encoded.decode("utf-8")
@@ -234,42 +238,48 @@ class OpenShiftAuthModule(AnsibleModule):
self,
argument_spec=K8S_AUTH_ARG_SPEC,
required_if=[
- ('state', 'present', ['username', 'password']),
- ('state', 'absent', ['api_key']),
- ]
+ ("state", "present", ["username", "password"]),
+ ("state", "absent", ["api_key"]),
+ ],
)
if not HAS_REQUESTS:
- self.fail("This module requires the python 'requests' package. Try `pip install requests`.")
+ self.fail(
+ "This module requires the python 'requests' package. Try `pip install requests`."
+ )
if not HAS_REQUESTS_OAUTH:
- self.fail("This module requires the python 'requests-oauthlib' package. Try `pip install requests-oauthlib`.")
+ self.fail(
+ "This module requires the python 'requests-oauthlib' package. Try `pip install requests-oauthlib`."
+ )
if not HAS_URLLIB3:
- self.fail("This module requires the python 'urllib3' package. Try `pip install urllib3`.")
+ self.fail(
+ "This module requires the python 'urllib3' package. Try `pip install urllib3`."
+ )
def execute_module(self):
- state = self.params.get('state')
- verify_ssl = self.params.get('validate_certs')
- ssl_ca_cert = self.params.get('ca_cert')
+ state = self.params.get("state")
+ verify_ssl = self.params.get("validate_certs")
+ ssl_ca_cert = self.params.get("ca_cert")
- self.auth_username = self.params.get('username')
- self.auth_password = self.params.get('password')
- self.auth_api_key = self.params.get('api_key')
- self.con_host = self.params.get('host')
+ self.auth_username = self.params.get("username")
+ self.auth_password = self.params.get("password")
+ self.auth_api_key = self.params.get("api_key")
+ self.con_host = self.params.get("host")
# python-requests takes either a bool or a path to a ca file as the 'verify' param
if verify_ssl and ssl_ca_cert:
self.con_verify_ca = ssl_ca_cert # path
else:
- self.con_verify_ca = verify_ssl # bool
+ self.con_verify_ca = verify_ssl # bool
# Get needed info to access authorization APIs
self.openshift_discover()
changed = False
result = dict()
- if state == 'present':
+ if state == "present":
new_api_key = self.openshift_login()
result = dict(
host=self.con_host,
@@ -285,87 +295,114 @@ class OpenShiftAuthModule(AnsibleModule):
self.exit_json(changed=changed, openshift_auth=result, k8s_auth=result)
def openshift_discover(self):
- url = urljoin(self.con_host, '.well-known/oauth-authorization-server')
+ url = urljoin(self.con_host, ".well-known/oauth-authorization-server")
ret = requests.get(url, verify=self.con_verify_ca)
if ret.status_code != 200:
- self.fail_request("Couldn't find OpenShift's OAuth API", method='GET', url=url,
- reason=ret.reason, status_code=ret.status_code)
+ self.fail_request(
+ "Couldn't find OpenShift's OAuth API",
+ method="GET",
+ url=url,
+ reason=ret.reason,
+ status_code=ret.status_code,
+ )
try:
oauth_info = ret.json()
- self.openshift_auth_endpoint = oauth_info['authorization_endpoint']
- self.openshift_token_endpoint = oauth_info['token_endpoint']
+ self.openshift_auth_endpoint = oauth_info["authorization_endpoint"]
+ self.openshift_token_endpoint = oauth_info["token_endpoint"]
except Exception:
- self.fail_json(msg="Something went wrong discovering OpenShift OAuth details.",
- exception=traceback.format_exc())
+ self.fail_json(
+ msg="Something went wrong discovering OpenShift OAuth details.",
+ exception=traceback.format_exc(),
+ )
def openshift_login(self):
- os_oauth = OAuth2Session(client_id='openshift-challenging-client')
- authorization_url, state = os_oauth.authorization_url(self.openshift_auth_endpoint,
- state="1", code_challenge_method='S256')
- auth_headers = make_headers(basic_auth='{0}:{1}'.format(self.auth_username, self.auth_password))
+ os_oauth = OAuth2Session(client_id="openshift-challenging-client")
+ authorization_url, state = os_oauth.authorization_url(
+ self.openshift_auth_endpoint, state="1", code_challenge_method="S256"
+ )
+ auth_headers = make_headers(
+ basic_auth="{0}:{1}".format(self.auth_username, self.auth_password)
+ )
# Request authorization code using basic auth credentials
ret = os_oauth.get(
authorization_url,
- headers={'X-Csrf-Token': state, 'authorization': auth_headers.get('authorization')},
+ headers={
+ "X-Csrf-Token": state,
+ "authorization": auth_headers.get("authorization"),
+ },
verify=self.con_verify_ca,
- allow_redirects=False
+ allow_redirects=False,
)
if ret.status_code != 302:
- self.fail_request("Authorization failed.", method='GET', url=authorization_url,
- reason=ret.reason, status_code=ret.status_code)
+ self.fail_request(
+ "Authorization failed.",
+ method="GET",
+ url=authorization_url,
+ reason=ret.reason,
+ status_code=ret.status_code,
+ )
# In here we have `code` and `state`, I think `code` is the important one
qwargs = {}
- for k, v in parse_qs(urlparse(ret.headers['Location']).query).items():
+ for k, v in parse_qs(urlparse(ret.headers["Location"]).query).items():
qwargs[k] = v[0]
- qwargs['grant_type'] = 'authorization_code'
+ qwargs["grant_type"] = "authorization_code"
# Using authorization code given to us in the Location header of the previous request, request a token
ret = os_oauth.post(
self.openshift_token_endpoint,
headers={
- 'Accept': 'application/json',
- 'Content-Type': 'application/x-www-form-urlencoded',
+ "Accept": "application/json",
+ "Content-Type": "application/x-www-form-urlencoded",
# This is just base64 encoded 'openshift-challenging-client:'
- 'Authorization': 'Basic b3BlbnNoaWZ0LWNoYWxsZW5naW5nLWNsaWVudDo='
+ "Authorization": "Basic b3BlbnNoaWZ0LWNoYWxsZW5naW5nLWNsaWVudDo=",
},
data=urlencode(qwargs),
- verify=self.con_verify_ca
+ verify=self.con_verify_ca,
)
if ret.status_code != 200:
- self.fail_request("Failed to obtain an authorization token.", method='POST',
- url=self.openshift_token_endpoint,
- reason=ret.reason, status_code=ret.status_code)
+ self.fail_request(
+ "Failed to obtain an authorization token.",
+ method="POST",
+ url=self.openshift_token_endpoint,
+ reason=ret.reason,
+ status_code=ret.status_code,
+ )
- return ret.json()['access_token']
+ return ret.json()["access_token"]
def openshift_logout(self):
-
name = get_oauthaccesstoken_objectname_from_token(self.auth_api_key)
headers = {
- 'Accept': 'application/json',
- 'Content-Type': 'application/json',
- 'Authorization': "Bearer {0}".format(self.auth_api_key)
+ "Accept": "application/json",
+ "Content-Type": "application/json",
+ "Authorization": "Bearer {0}".format(self.auth_api_key),
}
- url = "{0}/apis/oauth.openshift.io/v1/useroauthaccesstokens/{1}".format(self.con_host, name)
+ url = "{0}/apis/oauth.openshift.io/v1/useroauthaccesstokens/{1}".format(
+ self.con_host, name
+ )
json = {
"apiVersion": "oauth.openshift.io/v1",
"kind": "DeleteOptions",
- "gracePeriodSeconds": 0
+ "gracePeriodSeconds": 0,
}
- ret = requests.delete(url, json=json, verify=self.con_verify_ca, headers=headers)
+ ret = requests.delete(
+ url, json=json, verify=self.con_verify_ca, headers=headers
+ )
if ret.status_code != 200:
self.fail_json(
- msg="Couldn't delete user oauth access token '{0}' due to: {1}".format(name, ret.json().get("message")),
- status_code=ret.status_code
+ msg="Couldn't delete user oauth access token '{0}' due to: {1}".format(
+ name, ret.json().get("message")
+ ),
+ status_code=ret.status_code,
)
return True
@@ -376,7 +413,7 @@ class OpenShiftAuthModule(AnsibleModule):
def fail_request(self, msg, **kwargs):
req_info = {}
for k, v in kwargs.items():
- req_info['req_' + k] = v
+ req_info["req_" + k] = v
self.fail_json(msg=msg, **req_info)
@@ -388,5 +425,5 @@ def main():
module.fail_json(msg=str(e), exception=traceback.format_exc())
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/plugins/modules/openshift_build.py b/plugins/modules/openshift_build.py
index 1259a10..b397e23 100644
--- a/plugins/modules/openshift_build.py
+++ b/plugins/modules/openshift_build.py
@@ -5,10 +5,11 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
# STARTREMOVE (downstream)
-DOCUMENTATION = r'''
+DOCUMENTATION = r"""
module: openshift_build
@@ -134,9 +135,9 @@ options:
requirements:
- python >= 3.6
- kubernetes >= 12.0.0
-'''
+"""
-EXAMPLES = r'''
+EXAMPLES = r"""
# Starts build from build config default/hello-world
- name: Starts build from build config
community.okd.openshift_build:
@@ -171,9 +172,9 @@ EXAMPLES = r'''
build_phases:
- New
state: cancelled
-'''
+"""
-RETURN = r'''
+RETURN = r"""
builds:
description:
- The builds that were started/cancelled.
@@ -200,37 +201,47 @@ builds:
description: Current status details for the object.
returned: success
type: dict
-'''
+"""
# ENDREMOVE (downstream)
import copy
-from ansible_collections.kubernetes.core.plugins.module_utils.args_common import AUTH_ARG_SPEC
+from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
+ AUTH_ARG_SPEC,
+)
def argument_spec():
args = copy.deepcopy(AUTH_ARG_SPEC)
args_options = dict(
- name=dict(type='str', required=True),
- value=dict(type='str', required=True)
+ name=dict(type="str", required=True), value=dict(type="str", required=True)
)
args.update(
dict(
- state=dict(type='str', choices=['started', 'cancelled', 'restarted'], default="started"),
- build_args=dict(type='list', elements='dict', options=args_options),
- commit=dict(type='str'),
- env_vars=dict(type='list', elements='dict', options=args_options),
- build_name=dict(type='str'),
- build_config_name=dict(type='str'),
- namespace=dict(type='str', required=True),
- incremental=dict(type='bool'),
- no_cache=dict(type='bool'),
- wait=dict(type='bool', default=False),
- wait_sleep=dict(type='int', default=5),
- wait_timeout=dict(type='int', default=120),
- build_phases=dict(type='list', elements='str', default=[], choices=["New", "Pending", "Running"]),
+ state=dict(
+ type="str",
+ choices=["started", "cancelled", "restarted"],
+ default="started",
+ ),
+ build_args=dict(type="list", elements="dict", options=args_options),
+ commit=dict(type="str"),
+ env_vars=dict(type="list", elements="dict", options=args_options),
+ build_name=dict(type="str"),
+ build_config_name=dict(type="str"),
+ namespace=dict(type="str", required=True),
+ incremental=dict(type="bool"),
+ no_cache=dict(type="bool"),
+ wait=dict(type="bool", default=False),
+ wait_sleep=dict(type="int", default=5),
+ wait_timeout=dict(type="int", default=120),
+ build_phases=dict(
+ type="list",
+ elements="str",
+ default=[],
+ choices=["New", "Pending", "Running"],
+ ),
)
)
return args
@@ -238,23 +249,24 @@ def argument_spec():
def main():
mutually_exclusive = [
- ('build_name', 'build_config_name'),
+ ("build_name", "build_config_name"),
]
from ansible_collections.community.okd.plugins.module_utils.openshift_builds import (
- OpenShiftBuilds
+ OpenShiftBuilds,
)
+
module = OpenShiftBuilds(
argument_spec=argument_spec(),
mutually_exclusive=mutually_exclusive,
required_one_of=[
[
- 'build_name',
- 'build_config_name',
+ "build_name",
+ "build_config_name",
]
],
)
module.run_module()
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/plugins/modules/openshift_import_image.py b/plugins/modules/openshift_import_image.py
index df0588c..e5f371b 100644
--- a/plugins/modules/openshift_import_image.py
+++ b/plugins/modules/openshift_import_image.py
@@ -5,10 +5,11 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
# STARTREMOVE (downstream)
-DOCUMENTATION = r'''
+DOCUMENTATION = r"""
module: openshift_import_image
@@ -75,9 +76,9 @@ requirements:
- python >= 3.6
- kubernetes >= 12.0.0
- docker-image-py
-'''
+"""
-EXAMPLES = r'''
+EXAMPLES = r"""
# Import tag latest into a new image stream.
- name: Import tag latest into new image stream
community.okd.openshift_import_image:
@@ -122,10 +123,10 @@ EXAMPLES = r'''
- mystream3
source: registry.io/repo/image:latest
all: true
-'''
+"""
-RETURN = r'''
+RETURN = r"""
result:
description:
- List with all ImageStreamImport that have been created.
@@ -153,42 +154,44 @@ result:
description: Current status details for the object.
returned: success
type: dict
-'''
+"""
# ENDREMOVE (downstream)
import copy
-from ansible_collections.kubernetes.core.plugins.module_utils.args_common import AUTH_ARG_SPEC
+from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
+ AUTH_ARG_SPEC,
+)
def argument_spec():
args = copy.deepcopy(AUTH_ARG_SPEC)
args.update(
dict(
- namespace=dict(type='str', required=True),
- name=dict(type='raw', required=True),
- all=dict(type='bool', default=False),
- validate_registry_certs=dict(type='bool'),
- reference_policy=dict(type='str', choices=["source", "local"], default="source"),
- scheduled=dict(type='bool', default=False),
- source=dict(type='str'),
+ namespace=dict(type="str", required=True),
+ name=dict(type="raw", required=True),
+ all=dict(type="bool", default=False),
+ validate_registry_certs=dict(type="bool"),
+ reference_policy=dict(
+ type="str", choices=["source", "local"], default="source"
+ ),
+ scheduled=dict(type="bool", default=False),
+ source=dict(type="str"),
)
)
return args
def main():
-
from ansible_collections.community.okd.plugins.module_utils.openshift_import_image import (
- OpenShiftImportImage
+ OpenShiftImportImage,
)
module = OpenShiftImportImage(
- argument_spec=argument_spec(),
- supports_check_mode=True
+ argument_spec=argument_spec(), supports_check_mode=True
)
module.run_module()
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/plugins/modules/openshift_process.py b/plugins/modules/openshift_process.py
index fb00ffb..01b1bda 100644
--- a/plugins/modules/openshift_process.py
+++ b/plugins/modules/openshift_process.py
@@ -2,13 +2,14 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
# Copyright (c) 2020-2021, Red Hat
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
# STARTREMOVE (downstream)
-DOCUMENTATION = r'''
+DOCUMENTATION = r"""
module: openshift_process
short_description: Process an OpenShift template.openshift.io/v1 Template
@@ -49,6 +50,7 @@ options:
description:
- The namespace that resources should be created, updated, or deleted in.
- Only used when I(state) is present or absent.
+ type: str
parameters:
description:
- 'A set of key: value pairs that will be used to set/override values in the Template.'
@@ -70,9 +72,9 @@ options:
type: str
default: rendered
choices: [ absent, present, rendered ]
-'''
+"""
-EXAMPLES = r'''
+EXAMPLES = r"""
- name: Process a template in the cluster
community.okd.openshift_process:
name: nginx-example
@@ -87,8 +89,8 @@ EXAMPLES = r'''
community.okd.k8s:
namespace: default
definition: '{{ item }}'
- wait: yes
- apply: yes
+ wait: true
+ apply: true
loop: '{{ result.resources }}'
- name: Process a template with parameters from an env file and create the resources
@@ -98,7 +100,7 @@ EXAMPLES = r'''
namespace_target: default
parameter_file: 'files/nginx.env'
state: present
- wait: yes
+ wait: true
- name: Process a local template and create the resources
community.okd.openshift_process:
@@ -113,10 +115,10 @@ EXAMPLES = r'''
parameter_file: files/example.env
namespace_target: default
state: absent
- wait: yes
-'''
+ wait: true
+"""
-RETURN = r'''
+RETURN = r"""
result:
description:
- The created, patched, or otherwise present object. Will be empty in the case of a deletion.
@@ -200,11 +202,13 @@ resources:
conditions:
type: complex
description: Array of status conditions for the object. Not guaranteed to be present
-'''
+"""
# ENDREMOVE (downstream)
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
- AUTH_ARG_SPEC, RESOURCE_ARG_SPEC, WAIT_ARG_SPEC
+ AUTH_ARG_SPEC,
+ RESOURCE_ARG_SPEC,
+ WAIT_ARG_SPEC,
)
@@ -213,24 +217,26 @@ def argspec():
argument_spec.update(AUTH_ARG_SPEC)
argument_spec.update(WAIT_ARG_SPEC)
argument_spec.update(RESOURCE_ARG_SPEC)
- argument_spec['state'] = dict(type='str', default='rendered', choices=['present', 'absent', 'rendered'])
- argument_spec['namespace'] = dict(type='str')
- argument_spec['namespace_target'] = dict(type='str')
- argument_spec['parameters'] = dict(type='dict')
- argument_spec['name'] = dict(type='str')
- argument_spec['parameter_file'] = dict(type='str')
+ argument_spec["state"] = dict(
+ type="str", default="rendered", choices=["present", "absent", "rendered"]
+ )
+ argument_spec["namespace"] = dict(type="str")
+ argument_spec["namespace_target"] = dict(type="str")
+ argument_spec["parameters"] = dict(type="dict")
+ argument_spec["name"] = dict(type="str")
+ argument_spec["parameter_file"] = dict(type="str")
return argument_spec
def main():
-
from ansible_collections.community.okd.plugins.module_utils.openshift_process import (
- OpenShiftProcess)
+ OpenShiftProcess,
+ )
module = OpenShiftProcess(argument_spec=argspec(), supports_check_mode=True)
module.run_module()
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/plugins/modules/openshift_registry_info.py b/plugins/modules/openshift_registry_info.py
index a455ac5..2693d25 100644
--- a/plugins/modules/openshift_registry_info.py
+++ b/plugins/modules/openshift_registry_info.py
@@ -5,10 +5,11 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
# STARTREMOVE (downstream)
-DOCUMENTATION = r'''
+DOCUMENTATION = r"""
module: openshift_registry_info
@@ -40,9 +41,9 @@ requirements:
- python >= 3.6
- kubernetes >= 12.0.0
- docker-image-py
-'''
+"""
-EXAMPLES = r'''
+EXAMPLES = r"""
# Get registry information
- name: Read integrated registry information
community.okd.openshift_registry_info:
@@ -50,11 +51,11 @@ EXAMPLES = r'''
# Read registry integrated information and attempt to contact using local client.
- name: Attempt to contact integrated registry using local client
community.okd.openshift_registry_info:
- check: yes
-'''
+ check: true
+"""
-RETURN = r'''
+RETURN = r"""
internal_hostname:
description:
- The internal registry hostname.
@@ -79,36 +80,30 @@ check:
description: message describing the ping operation.
returned: always
type: str
-'''
+"""
# ENDREMOVE (downstream)
import copy
-from ansible_collections.kubernetes.core.plugins.module_utils.args_common import AUTH_ARG_SPEC
+from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
+ AUTH_ARG_SPEC,
+)
def argument_spec():
args = copy.deepcopy(AUTH_ARG_SPEC)
- args.update(
- dict(
- check=dict(type='bool', default=False)
- )
- )
+ args.update(dict(check=dict(type="bool", default=False)))
return args
def main():
-
from ansible_collections.community.okd.plugins.module_utils.openshift_registry import (
- OpenShiftRegistry
+ OpenShiftRegistry,
)
- module = OpenShiftRegistry(
- argument_spec=argument_spec(),
- supports_check_mode=True
- )
+ module = OpenShiftRegistry(argument_spec=argument_spec(), supports_check_mode=True)
module.run_module()
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/plugins/modules/openshift_route.py b/plugins/modules/openshift_route.py
index e452fc5..ea73db7 100644
--- a/plugins/modules/openshift_route.py
+++ b/plugins/modules/openshift_route.py
@@ -9,7 +9,7 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type
# STARTREMOVE (downstream)
-DOCUMENTATION = r'''
+DOCUMENTATION = r"""
module: openshift_route
short_description: Expose a Service as an OpenShift Route.
@@ -133,9 +133,9 @@ options:
- insecure
default: insecure
type: str
-'''
+"""
-EXAMPLES = r'''
+EXAMPLES = r"""
- name: Create hello-world deployment
community.okd.k8s:
definition:
@@ -155,10 +155,10 @@ EXAMPLES = r'''
app: hello-kubernetes
spec:
containers:
- - name: hello-kubernetes
- image: paulbouwer/hello-kubernetes:1.8
- ports:
- - containerPort: 8080
+ - name: hello-kubernetes
+ image: paulbouwer/hello-kubernetes:1.8
+ ports:
+ - containerPort: 8080
- name: Create Service for the hello-world deployment
community.okd.k8s:
@@ -170,8 +170,8 @@ EXAMPLES = r'''
namespace: default
spec:
ports:
- - port: 80
- targetPort: 8080
+ - port: 80
+ targetPort: 8080
selector:
app: hello-kubernetes
@@ -183,9 +183,9 @@ EXAMPLES = r'''
annotations:
haproxy.router.openshift.io/balance: roundrobin
register: route
-'''
+"""
-RETURN = r'''
+RETURN = r"""
result:
description:
- The Route object that was created or updated. Will be empty in the case of deletion.
@@ -303,20 +303,28 @@ duration:
returned: when C(wait) is true
type: int
sample: 48
-'''
+"""
# ENDREMOVE (downstream)
import copy
from ansible.module_utils._text import to_native
-from ansible_collections.community.okd.plugins.module_utils.openshift_common import AnsibleOpenshiftModule
+from ansible_collections.community.okd.plugins.module_utils.openshift_common import (
+ AnsibleOpenshiftModule,
+)
try:
- from ansible_collections.kubernetes.core.plugins.module_utils.k8s.runner import perform_action
- from ansible_collections.kubernetes.core.plugins.module_utils.k8s.waiter import Waiter
+ from ansible_collections.kubernetes.core.plugins.module_utils.k8s.runner import (
+ perform_action,
+ )
+ from ansible_collections.kubernetes.core.plugins.module_utils.k8s.waiter import (
+ Waiter,
+ )
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
- AUTH_ARG_SPEC, WAIT_ARG_SPEC, COMMON_ARG_SPEC
+ AUTH_ARG_SPEC,
+ WAIT_ARG_SPEC,
+ COMMON_ARG_SPEC,
)
except ImportError as e:
pass
@@ -329,7 +337,6 @@ except ImportError:
class OpenShiftRoute(AnsibleOpenshiftModule):
-
def __init__(self):
super(OpenShiftRoute, self).__init__(
argument_spec=self.argspec,
@@ -339,7 +346,7 @@ class OpenShiftRoute(AnsibleOpenshiftModule):
self.append_hash = False
self.apply = False
self.warnings = []
- self.params['merge_type'] = None
+ self.params["merge_type"] = None
@property
def argspec(self):
@@ -347,80 +354,95 @@ class OpenShiftRoute(AnsibleOpenshiftModule):
spec.update(copy.deepcopy(WAIT_ARG_SPEC))
spec.update(copy.deepcopy(COMMON_ARG_SPEC))
- spec['service'] = dict(type='str', aliases=['svc'])
- spec['namespace'] = dict(required=True, type='str')
- spec['labels'] = dict(type='dict')
- spec['name'] = dict(type='str')
- spec['hostname'] = dict(type='str')
- spec['path'] = dict(type='str')
- spec['wildcard_policy'] = dict(choices=['Subdomain'], type='str')
- spec['port'] = dict(type='str')
- spec['tls'] = dict(type='dict', options=dict(
- ca_certificate=dict(type='str'),
- certificate=dict(type='str'),
- destination_ca_certificate=dict(type='str'),
- key=dict(type='str', no_log=False),
- insecure_policy=dict(type='str', choices=['allow', 'redirect', 'disallow'], default='disallow'),
- ))
- spec['termination'] = dict(choices=['edge', 'passthrough', 'reencrypt', 'insecure'], default='insecure')
- spec['annotations'] = dict(type='dict')
+ spec["service"] = dict(type="str", aliases=["svc"])
+ spec["namespace"] = dict(required=True, type="str")
+ spec["labels"] = dict(type="dict")
+ spec["name"] = dict(type="str")
+ spec["hostname"] = dict(type="str")
+ spec["path"] = dict(type="str")
+ spec["wildcard_policy"] = dict(choices=["Subdomain"], type="str")
+ spec["port"] = dict(type="str")
+ spec["tls"] = dict(
+ type="dict",
+ options=dict(
+ ca_certificate=dict(type="str"),
+ certificate=dict(type="str"),
+ destination_ca_certificate=dict(type="str"),
+ key=dict(type="str", no_log=False),
+ insecure_policy=dict(
+ type="str",
+ choices=["allow", "redirect", "disallow"],
+ default="disallow",
+ ),
+ ),
+ )
+ spec["termination"] = dict(
+ choices=["edge", "passthrough", "reencrypt", "insecure"], default="insecure"
+ )
+ spec["annotations"] = dict(type="dict")
return spec
def execute_module(self):
-
- service_name = self.params.get('service')
- namespace = self.params['namespace']
- termination_type = self.params.get('termination')
- if termination_type == 'insecure':
+ service_name = self.params.get("service")
+ namespace = self.params["namespace"]
+ termination_type = self.params.get("termination")
+ if termination_type == "insecure":
termination_type = None
- state = self.params.get('state')
+ state = self.params.get("state")
- if state != 'absent' and not service_name:
+ if state != "absent" and not service_name:
self.fail_json("If 'state' is not 'absent' then 'service' must be provided")
# We need to do something a little wonky to wait if the user doesn't supply a custom condition
- custom_wait = self.params.get('wait') and not self.params.get('wait_condition') and state != 'absent'
+ custom_wait = (
+ self.params.get("wait")
+ and not self.params.get("wait_condition")
+ and state != "absent"
+ )
if custom_wait:
# Don't use default wait logic in perform_action
- self.params['wait'] = False
+ self.params["wait"] = False
- route_name = self.params.get('name') or service_name
- labels = self.params.get('labels')
- hostname = self.params.get('hostname')
- path = self.params.get('path')
- wildcard_policy = self.params.get('wildcard_policy')
- port = self.params.get('port')
- annotations = self.params.get('annotations')
+ route_name = self.params.get("name") or service_name
+ labels = self.params.get("labels")
+ hostname = self.params.get("hostname")
+ path = self.params.get("path")
+ wildcard_policy = self.params.get("wildcard_policy")
+ port = self.params.get("port")
+ annotations = self.params.get("annotations")
- if termination_type and self.params.get('tls'):
- tls_ca_cert = self.params['tls'].get('ca_certificate')
- tls_cert = self.params['tls'].get('certificate')
- tls_dest_ca_cert = self.params['tls'].get('destination_ca_certificate')
- tls_key = self.params['tls'].get('key')
- tls_insecure_policy = self.params['tls'].get('insecure_policy')
- if tls_insecure_policy == 'disallow':
+ if termination_type and self.params.get("tls"):
+ tls_ca_cert = self.params["tls"].get("ca_certificate")
+ tls_cert = self.params["tls"].get("certificate")
+ tls_dest_ca_cert = self.params["tls"].get("destination_ca_certificate")
+ tls_key = self.params["tls"].get("key")
+ tls_insecure_policy = self.params["tls"].get("insecure_policy")
+ if tls_insecure_policy == "disallow":
tls_insecure_policy = None
else:
- tls_ca_cert = tls_cert = tls_dest_ca_cert = tls_key = tls_insecure_policy = None
+ tls_ca_cert = (
+ tls_cert
+ ) = tls_dest_ca_cert = tls_key = tls_insecure_policy = None
route = {
- 'apiVersion': 'route.openshift.io/v1',
- 'kind': 'Route',
- 'metadata': {
- 'name': route_name,
- 'namespace': namespace,
- 'labels': labels,
+ "apiVersion": "route.openshift.io/v1",
+ "kind": "Route",
+ "metadata": {
+ "name": route_name,
+ "namespace": namespace,
+ "labels": labels,
},
- 'spec': {}
+ "spec": {},
}
if annotations:
- route['metadata']['annotations'] = annotations
+ route["metadata"]["annotations"] = annotations
- if state != 'absent':
- route['spec'] = self.build_route_spec(
- service_name, namespace,
+ if state != "absent":
+ route["spec"] = self.build_route_spec(
+ service_name,
+ namespace,
port=port,
wildcard_policy=wildcard_policy,
hostname=hostname,
@@ -434,79 +456,120 @@ class OpenShiftRoute(AnsibleOpenshiftModule):
)
result = perform_action(self.svc, route, self.params)
- timeout = self.params.get('wait_timeout')
- sleep = self.params.get('wait_sleep')
+ timeout = self.params.get("wait_timeout")
+ sleep = self.params.get("wait_sleep")
if custom_wait:
- v1_routes = self.find_resource('Route', 'route.openshift.io/v1', fail=True)
+ v1_routes = self.find_resource("Route", "route.openshift.io/v1", fail=True)
waiter = Waiter(self.client, v1_routes, wait_predicate)
- success, result['result'], result['duration'] = waiter.wait(timeout=timeout, sleep=sleep, name=route_name, namespace=namespace)
+ success, result["result"], result["duration"] = waiter.wait(
+ timeout=timeout, sleep=sleep, name=route_name, namespace=namespace
+ )
self.exit_json(**result)
- def build_route_spec(self, service_name, namespace, port=None, wildcard_policy=None, hostname=None, path=None, termination_type=None,
- tls_insecure_policy=None, tls_ca_cert=None, tls_cert=None, tls_key=None, tls_dest_ca_cert=None):
- v1_services = self.find_resource('Service', 'v1', fail=True)
+ def build_route_spec(
+ self,
+ service_name,
+ namespace,
+ port=None,
+ wildcard_policy=None,
+ hostname=None,
+ path=None,
+ termination_type=None,
+ tls_insecure_policy=None,
+ tls_ca_cert=None,
+ tls_cert=None,
+ tls_key=None,
+ tls_dest_ca_cert=None,
+ ):
+ v1_services = self.find_resource("Service", "v1", fail=True)
try:
target_service = v1_services.get(name=service_name, namespace=namespace)
except NotFoundError:
if not port:
- self.fail_json(msg="You need to provide the 'port' argument when exposing a non-existent service")
+ self.fail_json(
+ msg="You need to provide the 'port' argument when exposing a non-existent service"
+ )
target_service = None
except DynamicApiError as exc:
- self.fail_json(msg='Failed to retrieve service to be exposed: {0}'.format(exc.body),
- error=exc.status, status=exc.status, reason=exc.reason)
+ self.fail_json(
+ msg="Failed to retrieve service to be exposed: {0}".format(exc.body),
+ error=exc.status,
+ status=exc.status,
+ reason=exc.reason,
+ )
except Exception as exc:
- self.fail_json(msg='Failed to retrieve service to be exposed: {0}'.format(to_native(exc)),
- error='', status='', reason='')
+ self.fail_json(
+ msg="Failed to retrieve service to be exposed: {0}".format(
+ to_native(exc)
+ ),
+ error="",
+ status="",
+ reason="",
+ )
route_spec = {
- 'tls': {},
- 'to': {
- 'kind': 'Service',
- 'name': service_name,
+ "tls": {},
+ "to": {
+ "kind": "Service",
+ "name": service_name,
},
- 'port': {
- 'targetPort': self.set_port(target_service, port),
+ "port": {
+ "targetPort": self.set_port(target_service, port),
},
- 'wildcardPolicy': wildcard_policy
+ "wildcardPolicy": wildcard_policy,
}
# Want to conditionally add these so we don't overwrite what is automically added when nothing is provided
if termination_type:
- route_spec['tls'] = dict(termination=termination_type.capitalize())
+ route_spec["tls"] = dict(termination=termination_type.capitalize())
if tls_insecure_policy:
- if termination_type == 'edge':
- route_spec['tls']['insecureEdgeTerminationPolicy'] = tls_insecure_policy.capitalize()
- elif termination_type == 'passthrough':
- if tls_insecure_policy != 'redirect':
- self.fail_json("'redirect' is the only supported insecureEdgeTerminationPolicy for passthrough routes")
- route_spec['tls']['insecureEdgeTerminationPolicy'] = tls_insecure_policy.capitalize()
- elif termination_type == 'reencrypt':
- self.fail_json("'tls.insecure_policy' is not supported with reencrypt routes")
+ if termination_type == "edge":
+ route_spec["tls"][
+ "insecureEdgeTerminationPolicy"
+ ] = tls_insecure_policy.capitalize()
+ elif termination_type == "passthrough":
+ if tls_insecure_policy != "redirect":
+ self.fail_json(
+ "'redirect' is the only supported insecureEdgeTerminationPolicy for passthrough routes"
+ )
+ route_spec["tls"][
+ "insecureEdgeTerminationPolicy"
+ ] = tls_insecure_policy.capitalize()
+ elif termination_type == "reencrypt":
+ self.fail_json(
+ "'tls.insecure_policy' is not supported with reencrypt routes"
+ )
else:
- route_spec['tls']['insecureEdgeTerminationPolicy'] = None
+ route_spec["tls"]["insecureEdgeTerminationPolicy"] = None
if tls_ca_cert:
- if termination_type == 'passthrough':
- self.fail_json("'tls.ca_certificate' is not supported with passthrough routes")
- route_spec['tls']['caCertificate'] = tls_ca_cert
+ if termination_type == "passthrough":
+ self.fail_json(
+ "'tls.ca_certificate' is not supported with passthrough routes"
+ )
+ route_spec["tls"]["caCertificate"] = tls_ca_cert
if tls_cert:
- if termination_type == 'passthrough':
- self.fail_json("'tls.certificate' is not supported with passthrough routes")
- route_spec['tls']['certificate'] = tls_cert
+ if termination_type == "passthrough":
+ self.fail_json(
+ "'tls.certificate' is not supported with passthrough routes"
+ )
+ route_spec["tls"]["certificate"] = tls_cert
if tls_key:
- if termination_type == 'passthrough':
+ if termination_type == "passthrough":
self.fail_json("'tls.key' is not supported with passthrough routes")
- route_spec['tls']['key'] = tls_key
+ route_spec["tls"]["key"] = tls_key
if tls_dest_ca_cert:
- if termination_type != 'reencrypt':
- self.fail_json("'destination_certificate' is only valid for reencrypt routes")
- route_spec['tls']['destinationCACertificate'] = tls_dest_ca_cert
+ if termination_type != "reencrypt":
+ self.fail_json(
+ "'destination_certificate' is only valid for reencrypt routes"
+ )
+ route_spec["tls"]["destinationCACertificate"] = tls_dest_ca_cert
else:
- route_spec['tls'] = None
+ route_spec["tls"] = None
if hostname:
- route_spec['host'] = hostname
+ route_spec["host"] = hostname
if path:
- route_spec['path'] = path
+ route_spec["path"] = path
return route_spec
@@ -514,7 +577,7 @@ class OpenShiftRoute(AnsibleOpenshiftModule):
if port_arg:
return port_arg
for p in service.spec.ports:
- if p.protocol == 'TCP':
+ if p.protocol == "TCP":
if p.name is not None:
return p.name
return p.targetPort
@@ -525,7 +588,7 @@ def wait_predicate(route):
if not (route.status and route.status.ingress):
return False
for ingress in route.status.ingress:
- match = [x for x in ingress.conditions if x.type == 'Admitted']
+ match = [x for x in ingress.conditions if x.type == "Admitted"]
if not match:
return False
match = match[0]
@@ -538,5 +601,5 @@ def main():
OpenShiftRoute().run_module()
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/requirements.yml b/requirements.yml
index d7d4e6f..3c7976a 100644
--- a/requirements.yml
+++ b/requirements.yml
@@ -1,3 +1,4 @@
+---
collections:
- name: kubernetes.core
version: '>=2.4.0'
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 29c924b..0000000
--- a/setup.cfg
+++ /dev/null
@@ -1,3 +0,0 @@
-[flake8]
-max-line-length = 160
-ignore = W503,E402
diff --git a/test-requirements.txt b/test-requirements.txt
index 7f23468..99e8534 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -2,3 +2,4 @@ coverage==4.5.4
pytest
pytest-xdist
pytest-forked
+pytest-ansible
diff --git a/tests/config.yml b/tests/config.yml
index 9e402bd..c26ea59 100644
--- a/tests/config.yml
+++ b/tests/config.yml
@@ -1,2 +1,3 @@
+---
modules:
- python_requires: ">=3.6"
+ python_requires: ">=3.9"
diff --git a/tests/sanity/ignore-2.16.txt b/tests/sanity/ignore-2.16.txt
new file mode 100644
index 0000000..2fd2bdc
--- /dev/null
+++ b/tests/sanity/ignore-2.16.txt
@@ -0,0 +1,3 @@
+plugins/modules/k8s.py validate-modules:parameter-type-not-in-doc
+plugins/modules/k8s.py validate-modules:return-syntax-error
+plugins/modules/openshift_process.py validate-modules:parameter-type-not-in-doc
\ No newline at end of file
diff --git a/tests/sanity/ignore-2.17.txt b/tests/sanity/ignore-2.17.txt
new file mode 100644
index 0000000..2fd2bdc
--- /dev/null
+++ b/tests/sanity/ignore-2.17.txt
@@ -0,0 +1,3 @@
+plugins/modules/k8s.py validate-modules:parameter-type-not-in-doc
+plugins/modules/k8s.py validate-modules:return-syntax-error
+plugins/modules/openshift_process.py validate-modules:parameter-type-not-in-doc
\ No newline at end of file
diff --git a/tests/sanity/requirements.yml b/tests/sanity/requirements.yml
new file mode 100644
index 0000000..244be51
--- /dev/null
+++ b/tests/sanity/requirements.yml
@@ -0,0 +1,5 @@
+---
+collections:
+ - name: https://github.com/ansible-collections/kubernetes.core.git
+ type: git
+ version: main
diff --git a/tests/unit/plugins/module_utils/test_ldap_dn.py b/tests/unit/plugins/module_utils/test_ldap_dn.py
index 5835f36..c312f3b 100644
--- a/tests/unit/plugins/module_utils/test_ldap_dn.py
+++ b/tests/unit/plugins/module_utils/test_ldap_dn.py
@@ -5,28 +5,44 @@ __metaclass__ = type
from ansible_collections.community.okd.plugins.module_utils.openshift_ldap import (
openshift_equal_dn,
- openshift_ancestorof_dn
+ openshift_ancestorof_dn,
)
import pytest
try:
- import ldap
+ import ldap # pylint: disable=unused-import
except ImportError:
pytestmark = pytest.mark.skip("This test requires the python-ldap library")
def test_equal_dn():
-
- assert openshift_equal_dn("cn=unit,ou=users,dc=ansible,dc=com", "cn=unit,ou=users,dc=ansible,dc=com")
- assert not openshift_equal_dn("cn=unit,ou=users,dc=ansible,dc=com", "cn=units,ou=users,dc=ansible,dc=com")
- assert not openshift_equal_dn("cn=unit,ou=users,dc=ansible,dc=com", "cn=unit,ou=user,dc=ansible,dc=com")
- assert not openshift_equal_dn("cn=unit,ou=users,dc=ansible,dc=com", "cn=unit,ou=users,dc=ansible,dc=org")
+ assert openshift_equal_dn(
+ "cn=unit,ou=users,dc=ansible,dc=com", "cn=unit,ou=users,dc=ansible,dc=com"
+ )
+ assert not openshift_equal_dn(
+ "cn=unit,ou=users,dc=ansible,dc=com", "cn=units,ou=users,dc=ansible,dc=com"
+ )
+ assert not openshift_equal_dn(
+ "cn=unit,ou=users,dc=ansible,dc=com", "cn=unit,ou=user,dc=ansible,dc=com"
+ )
+ assert not openshift_equal_dn(
+ "cn=unit,ou=users,dc=ansible,dc=com", "cn=unit,ou=users,dc=ansible,dc=org"
+ )
def test_ancestor_of_dn():
-
- assert not openshift_ancestorof_dn("cn=unit,ou=users,dc=ansible,dc=com", "cn=unit,ou=users,dc=ansible,dc=com")
- assert not openshift_ancestorof_dn("cn=unit,ou=users,dc=ansible,dc=com", "cn=units,ou=users,dc=ansible,dc=com")
- assert openshift_ancestorof_dn("ou=users,dc=ansible,dc=com", "cn=john,ou=users,dc=ansible,dc=com")
- assert openshift_ancestorof_dn("ou=users,dc=ansible,dc=com", "cn=mathew,ou=users,dc=ansible,dc=com")
- assert not openshift_ancestorof_dn("ou=users,dc=ansible,dc=com", "cn=mathew,ou=users,dc=ansible,dc=org")
+ assert not openshift_ancestorof_dn(
+ "cn=unit,ou=users,dc=ansible,dc=com", "cn=unit,ou=users,dc=ansible,dc=com"
+ )
+ assert not openshift_ancestorof_dn(
+ "cn=unit,ou=users,dc=ansible,dc=com", "cn=units,ou=users,dc=ansible,dc=com"
+ )
+ assert openshift_ancestorof_dn(
+ "ou=users,dc=ansible,dc=com", "cn=john,ou=users,dc=ansible,dc=com"
+ )
+ assert openshift_ancestorof_dn(
+ "ou=users,dc=ansible,dc=com", "cn=mathew,ou=users,dc=ansible,dc=com"
+ )
+ assert not openshift_ancestorof_dn(
+ "ou=users,dc=ansible,dc=com", "cn=mathew,ou=users,dc=ansible,dc=org"
+ )
diff --git a/tests/unit/plugins/module_utils/test_ldap_sync_config.py b/tests/unit/plugins/module_utils/test_ldap_sync_config.py
index 1a8ef67..303b66f 100644
--- a/tests/unit/plugins/module_utils/test_ldap_sync_config.py
+++ b/tests/unit/plugins/module_utils/test_ldap_sync_config.py
@@ -9,28 +9,26 @@ from ansible_collections.community.okd.plugins.module_utils.openshift_ldap impor
def test_missing_url():
- config = dict(
- kind="LDAPSyncConfig",
- apiVersion="v1",
- insecure=True
- )
+ config = dict(kind="LDAPSyncConfig", apiVersion="v1", insecure=True)
err = validate_ldap_sync_config(config)
assert err == "url should be non empty attribute."
def test_binddn_and_bindpwd_linked():
"""
- one of bind_dn and bind_pwd cannot be set alone
+ one of bind_dn and bind_pwd cannot be set alone
"""
config = dict(
kind="LDAPSyncConfig",
apiVersion="v1",
url="ldap://LDAP_SERVICE_IP:389",
insecure=True,
- bindDN="cn=admin,dc=example,dc=org"
+ bindDN="cn=admin,dc=example,dc=org",
)
- credentials_error = "bindDN and bindPassword must both be specified, or both be empty."
+ credentials_error = (
+ "bindDN and bindPassword must both be specified, or both be empty."
+ )
assert validate_ldap_sync_config(config) == credentials_error
@@ -39,7 +37,7 @@ def test_binddn_and_bindpwd_linked():
apiVersion="v1",
url="ldap://LDAP_SERVICE_IP:389",
insecure=True,
- bindPassword="testing1223"
+ bindPassword="testing1223",
)
assert validate_ldap_sync_config(config) == credentials_error
@@ -53,11 +51,13 @@ def test_insecure_connection():
insecure=True,
)
- assert validate_ldap_sync_config(config) == "Cannot use ldaps scheme with insecure=true."
+ assert (
+ validate_ldap_sync_config(config)
+ == "Cannot use ldaps scheme with insecure=true."
+ )
- config.update(dict(
- url="ldap://LDAP_SERVICE_IP:389",
- ca="path/to/ca/file"
- ))
+ config.update(dict(url="ldap://LDAP_SERVICE_IP:389", ca="path/to/ca/file"))
- assert validate_ldap_sync_config(config) == "Cannot specify a ca with insecure=true."
+ assert (
+ validate_ldap_sync_config(config) == "Cannot specify a ca with insecure=true."
+ )
diff --git a/tests/unit/plugins/module_utils/test_openshift_docker_image.py b/tests/unit/plugins/module_utils/test_openshift_docker_image.py
index 99cf15c..d23f9f1 100644
--- a/tests/unit/plugins/module_utils/test_openshift_docker_image.py
+++ b/tests/unit/plugins/module_utils/test_openshift_docker_image.py
@@ -11,7 +11,6 @@ import pytest
def test_convert_storage_to_bytes():
-
data = [
("1000", 1000),
("1000Ki", 1000 * 1024),
@@ -54,46 +53,48 @@ def validate_docker_response(resp, **kwargs):
def test_parse_docker_image_ref_valid_image_with_digest():
-
image = "registry.access.redhat.com/ubi8/dotnet-21@sha256:f7718f5efd3436e781ee4322c92ab0c4ae63e61f5b36f1473a57874cc3522669"
response, err = parse_docker_image_ref(image)
assert err is None
- validate_docker_response(response,
- hostname="registry.access.redhat.com",
- namespace="ubi8",
- name="dotnet-21",
- digest="sha256:f7718f5efd3436e781ee4322c92ab0c4ae63e61f5b36f1473a57874cc3522669")
+ validate_docker_response(
+ response,
+ hostname="registry.access.redhat.com",
+ namespace="ubi8",
+ name="dotnet-21",
+ digest="sha256:f7718f5efd3436e781ee4322c92ab0c4ae63e61f5b36f1473a57874cc3522669",
+ )
def test_parse_docker_image_ref_valid_image_with_tag_latest():
-
image = "registry.access.redhat.com/ubi8/dotnet-21:latest"
response, err = parse_docker_image_ref(image)
assert err is None
- validate_docker_response(response,
- hostname="registry.access.redhat.com",
- namespace="ubi8",
- name="dotnet-21",
- tag="latest")
+ validate_docker_response(
+ response,
+ hostname="registry.access.redhat.com",
+ namespace="ubi8",
+ name="dotnet-21",
+ tag="latest",
+ )
def test_parse_docker_image_ref_valid_image_with_tag_int():
-
image = "registry.access.redhat.com/ubi8/dotnet-21:0.0.1"
response, err = parse_docker_image_ref(image)
assert err is None
- validate_docker_response(response,
- hostname="registry.access.redhat.com",
- namespace="ubi8",
- name="dotnet-21",
- tag="0.0.1")
+ validate_docker_response(
+ response,
+ hostname="registry.access.redhat.com",
+ namespace="ubi8",
+ name="dotnet-21",
+ tag="0.0.1",
+ )
def test_parse_docker_image_ref_invalid_image():
-
# The hex value of the sha256 is not valid
image = "registry.access.redhat.com/dotnet-21@sha256:f7718f5efd3436e781ee4322c92ab0c4ae63e61f5b36f1473a57874cc3522"
response, err = parse_docker_image_ref(image)
@@ -101,7 +102,6 @@ def test_parse_docker_image_ref_invalid_image():
def test_parse_docker_image_ref_valid_image_without_hostname():
-
image = "ansible:2.10.0"
response, err = parse_docker_image_ref(image)
assert err is None
@@ -110,16 +110,18 @@ def test_parse_docker_image_ref_valid_image_without_hostname():
def test_parse_docker_image_ref_valid_image_without_hostname_and_with_digest():
-
image = "ansible@sha256:f7718f5efd3436e781ee4322c92ab0c4ae63e61f5b36f1473a57874cc3522669"
response, err = parse_docker_image_ref(image)
assert err is None
- validate_docker_response(response, name="ansible", digest="sha256:f7718f5efd3436e781ee4322c92ab0c4ae63e61f5b36f1473a57874cc3522669")
+ validate_docker_response(
+ response,
+ name="ansible",
+ digest="sha256:f7718f5efd3436e781ee4322c92ab0c4ae63e61f5b36f1473a57874cc3522669",
+ )
def test_parse_docker_image_ref_valid_image_with_name_only():
-
image = "ansible"
response, err = parse_docker_image_ref(image)
assert err is None
@@ -128,25 +130,27 @@ def test_parse_docker_image_ref_valid_image_with_name_only():
def test_parse_docker_image_ref_valid_image_without_hostname_with_namespace_and_name():
-
image = "ibmcom/pause@sha256:fcaff905397ba63fd376d0c3019f1f1cb6e7506131389edbcb3d22719f1ae54d"
response, err = parse_docker_image_ref(image)
assert err is None
- validate_docker_response(response,
- name="pause",
- namespace="ibmcom",
- digest="sha256:fcaff905397ba63fd376d0c3019f1f1cb6e7506131389edbcb3d22719f1ae54d")
+ validate_docker_response(
+ response,
+ name="pause",
+ namespace="ibmcom",
+ digest="sha256:fcaff905397ba63fd376d0c3019f1f1cb6e7506131389edbcb3d22719f1ae54d",
+ )
def test_parse_docker_image_ref_valid_image_with_complex_namespace_name():
-
image = "registry.redhat.io/jboss-webserver-5/webserver54-openjdk11-tomcat9-openshift-rhel7:1.0"
response, err = parse_docker_image_ref(image)
assert err is None
- validate_docker_response(response,
- hostname="registry.redhat.io",
- name="webserver54-openjdk11-tomcat9-openshift-rhel7",
- namespace="jboss-webserver-5",
- tag="1.0")
+ validate_docker_response(
+ response,
+ hostname="registry.redhat.io",
+ name="webserver54-openjdk11-tomcat9-openshift-rhel7",
+ namespace="jboss-webserver-5",
+ tag="1.0",
+ )
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..57fd1d9
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,37 @@
+[tox]
+skipsdist = True
+
+[testenv]
+deps = -r{toxinidir}/requirements.txt
+ -r{toxinidir}/test-requirements.txt
+install_command = pip install {opts} {packages}
+
+[testenv:black]
+deps =
+ black >= 23.0, < 24.0
+
+commands =
+ black {toxinidir}/plugins {toxinidir}/tests
+
+[testenv:ansible-lint]
+deps =
+ ansible-lint==6.21.0
+changedir = {toxinidir}
+commands =
+ ansible-lint
+
+[testenv:linters]
+deps =
+ flake8
+ {[testenv:black]deps}
+
+commands =
+ black -v --check --diff {toxinidir}/plugins {toxinidir}/tests
+ flake8 {toxinidir}
+
+[flake8]
+# E123, E125 skipped as they are invalid PEP-8.
+exclude = .git,.tox,tests/output
+ignore = E123,E125,E203,E402,E501,E741,F401,F811,F841,W503
+max-line-length = 160
+builtins = _