From e0de1fa2f0d0f1cca59cefa7061c25688d53b5c6 Mon Sep 17 00:00:00 2001 From: Yemi Kelani Date: Fri, 3 May 2024 14:36:16 -0700 Subject: [PATCH 1/3] Added oc-zoscloudbroker module, overhauled tests (Ansible Sanity, Unit, and Integration tests, and refactored Molecule tests) and added shell scriptes to make testing locally easier. Signed-off-by: Yemi Kelani --- .github/workflows/test.yml | 131 +++++- .gitignore | 4 +- .../racf-operator/inventories/inventory.yml | 2 +- .../roles/add-zos-user/defaults/main.yml | 2 +- .../roles/remove-zos-user/vars/main.yml | 2 +- ibm/operator_collection_sdk/galaxy.yml | 73 ++++ .../playbooks/molecule/cluster_clean.yml | 9 +- .../playbooks/molecule/cluster_setup.yml | 9 +- .../create_offline_requirements/destroy.yml | 1 - .../create_offline_requirements/verify.yml | 2 +- .../destroy.yml | 1 - .../verify.yml | 2 +- .../create_operator_config/verify.yml | 30 +- .../create_operator_local/converge.yml | 101 ++++- .../create_operator_local/destroy.yml | 79 +++- .../create_operator_local/molecule.yml | 5 +- .../create_operator_local/prepare.yml | 3 + .../molecule/create_operator_local/verify.yml | 37 +- .../converge.yml | 100 ++++- .../destroy.yml | 89 +++- .../molecule.yml | 5 +- .../prepare.yml | 3 + .../verify.yml | 45 +- .../molecule/init_collection/destroy.yml | 1 - .../molecule/init_collection/verify.yml | 46 +- .../init_collection_offline/destroy.yml | 1 - .../init_collection_offline/verify.yml | 42 +- .../playbooks/redeploy_operator.yml | 1 - .../playbooks/templates/zoscloudbroker.yml.j2 | 37 ++ .../plugins/doc_fragments/__init__.py | 0 .../plugins/module_utils/__init__.py | 0 .../plugins/module_utils/util.py | 52 +++ .../plugins/modules/__init__.py | 0 .../plugins/modules/oc_operatorcollection.py | 9 +- .../plugins/modules/oc_suboperatorconfig.py | 2 +- .../plugins/modules/oc_zoscloudbroker.py | 404 ++++++++++++++++++ .../plugins/modules/oc_zosendpoint.py | 2 +- .../tasks/main.yml | 63 +++ ibm/operator_collection_sdk/tests/README.md | 43 ++ .../tests/integration/integration.sh | 107 +++++ .../tests/integration/integration_clean.sh | 60 +++ .../integration_config.yml.template | 11 + .../tests/integration/integration_setup.sh | 55 +++ .../tests/integration/requirements.txt | 2 + .../tests/integration/requirements.yml | 2 + .../targets/oc_zoscloudbroker/playbook.yml | 13 + .../targets/oc_zoscloudbroker/runme.sh | 4 + .../targets/oc_zoscloudbroker/tasks/main.yml | 94 ++++ .../tasks/revert_changes.yml | 28 ++ .../tests/sanity/ignore-2.16.txt | 7 + .../tests/sanity/ignore-2.9.txt | 4 + .../tests/sanity/sanity.sh | 60 +++ .../tests/unit/__init__.py | 0 .../tests/unit/modules/__init__.py | 0 .../unit/modules/test_oc_zoscloudbroker.py | 152 +++++++ .../tests/unit/requirements.txt | 3 + .../tests/unit/unit.sh | 60 +++ .../tests/unit/utils/__init__.py | 0 .../tests/unit/utils/mock.py | 49 +++ 59 files changed, 1990 insertions(+), 159 deletions(-) create mode 100644 ibm/operator_collection_sdk/playbooks/templates/zoscloudbroker.yml.j2 create mode 100644 ibm/operator_collection_sdk/plugins/doc_fragments/__init__.py create mode 100644 ibm/operator_collection_sdk/plugins/module_utils/__init__.py create mode 100644 ibm/operator_collection_sdk/plugins/module_utils/util.py create mode 100644 ibm/operator_collection_sdk/plugins/modules/__init__.py create mode 100644 ibm/operator_collection_sdk/plugins/modules/oc_zoscloudbroker.py create mode 100644 ibm/operator_collection_sdk/tests/README.md create mode 100755 ibm/operator_collection_sdk/tests/integration/integration.sh create mode 100755 ibm/operator_collection_sdk/tests/integration/integration_clean.sh create mode 100644 ibm/operator_collection_sdk/tests/integration/integration_config.yml.template create mode 100755 ibm/operator_collection_sdk/tests/integration/integration_setup.sh create mode 100644 ibm/operator_collection_sdk/tests/integration/requirements.txt create mode 100644 ibm/operator_collection_sdk/tests/integration/requirements.yml create mode 100644 ibm/operator_collection_sdk/tests/integration/targets/oc_zoscloudbroker/playbook.yml create mode 100755 ibm/operator_collection_sdk/tests/integration/targets/oc_zoscloudbroker/runme.sh create mode 100644 ibm/operator_collection_sdk/tests/integration/targets/oc_zoscloudbroker/tasks/main.yml create mode 100644 ibm/operator_collection_sdk/tests/integration/targets/oc_zoscloudbroker/tasks/revert_changes.yml create mode 100644 ibm/operator_collection_sdk/tests/sanity/ignore-2.9.txt create mode 100755 ibm/operator_collection_sdk/tests/sanity/sanity.sh create mode 100644 ibm/operator_collection_sdk/tests/unit/__init__.py create mode 100644 ibm/operator_collection_sdk/tests/unit/modules/__init__.py create mode 100644 ibm/operator_collection_sdk/tests/unit/modules/test_oc_zoscloudbroker.py create mode 100644 ibm/operator_collection_sdk/tests/unit/requirements.txt create mode 100755 ibm/operator_collection_sdk/tests/unit/unit.sh create mode 100644 ibm/operator_collection_sdk/tests/unit/utils/__init__.py create mode 100644 ibm/operator_collection_sdk/tests/unit/utils/mock.py diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ede48262..81202ebd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,14 +5,21 @@ name: Test on: push: branches: - - '**' + - "**" paths-ignore: - - 'docs/**' - - '**.md' + - "docs/**" + - "**.md" tags-ignore: - - '**' + - "**" pull_request_target: +concurrency: + group: >- + ${{ github.workflow }}-${{ + github.event.pull_request.number || github.sha + }} + cancel-in-progress: true + jobs: authorize: name: Authorize @@ -39,8 +46,8 @@ jobs: - name: Install Python Requirements uses: actions/setup-python@v4 with: - python-version: '3.10' - cache: 'pip' + python-version: "3.10" + cache: "pip" - name: Perform PIP installs run: pip install ansible-lint==6.16.0 @@ -53,8 +60,100 @@ jobs: ansible-galaxy collection install --force -r ${GITHUB_WORKSPACE}/ibm/operator_collection_sdk/requirements.yml ansible-lint --config-file ${GITHUB_WORKSPACE}/ibm/operator_collection_sdk/.ansible-lint --project-dir ${GITHUB_WORKSPACE}/ibm/operator_collection_sdk/playbooks/ --exclude ${GITHUB_WORKSPACE}/ibm/operator_collection_sdk/playbooks/molecule/ - test: - name: Test + sanity: + name: Run Sanity Tests (Ⓐ${{ matrix.ansible }}) + needs: [lint, authorize] + runs-on: >- + ${{ contains(fromJson( + '["stable-2.9", "stable-2.10", "stable-2.11"]' + ), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }} + strategy: + matrix: + ansible: + - stable-2.16 + # - milestone + steps: + - name: Perform sanity testing with ansible-test + uses: ansible-community/ansible-test-gh-action@release/v1 + with: + collection-root: /ibm/operator_collection_sdk/ + ansible-core-version: stable-2.16 + testing-type: sanity + + unit: + name: Run Unit Tests (Ⓐ${{ matrix.ansible }}) + needs: [lint, authorize] + runs-on: >- + ${{ contains(fromJson( + '["stable-2.9", "stable-2.10", "stable-2.11"]' + ), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }} + strategy: + matrix: + ansible: + - stable-2.16 + steps: + - name: Perform unit testing with ansible-test + uses: ansible-community/ansible-test-gh-action@release/v1 + with: + collection-root: /ibm/operator_collection_sdk/ + ansible-core-version: stable-2.16 + target-python-version: 3.11 + testing-type: units + test-deps: >- + kubernetes.core + + integration: + name: Run Integration Tests + needs: [lint, authorize] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Log into OCP + uses: redhat-actions/oc-login@v1 + with: + openshift_server_url: ${{ secrets.OPENSHIFT_SERVER }} + openshift_token: ${{ secrets.OPENSHIFT_TOKEN }} + + - name: Setup Cluster Environment before integration Tests + continue-on-error: true + run: | + chmod +x ${GITHUB_WORKSPACE}/ibm/operator_collection_sdk/tests/integration/integration_setup.sh + bash ${GITHUB_WORKSPACE}/ibm/operator_collection_sdk/tests/integration/integration_setup.sh \ + --collection-root=${GITHUB_WORKSPACE}/ibm/operator_collection_sdk + env: + OCP_NAMESPACE: integration-${GITHUB_REF_NAME}-${RUNNER_OS} + ZOSCB_RELEASE: ibm-zoscb.${{ vars.ZOSCB_RELEASE }} + + - name: Install Python Requirements + uses: actions/setup-python@v4 + with: + python-version: "3.11" + cache: "pip" + + - name: Perform PIP and Collection Installs + run: | + pip install -r ${GITHUB_WORKSPACE}/ibm/operator_collection_sdk/tests/integration/requirements.txt + ansible-galaxy collection install --force -r ${GITHUB_WORKSPACE}/ibm/operator_collection_sdk/tests/integration/requirements.yml + ansible-galaxy collection install ${GITHUB_WORKSPACE}/ibm/operator_collection_sdk --force + + - name: Perform Integration Testing with ansible-test + run: | + cd ~/.ansible/collections/ansible_collections/ibm/operator_collection_sdk + ansible-test integration -v + + - name: Cleanup Cluster Environment after integration Tests + if: always() + run: | + chmod +x ${GITHUB_WORKSPACE}/ibm/operator_collection_sdk/tests/integration/integration_clean.sh + bash ${GITHUB_WORKSPACE}/ibm/operator_collection_sdk/tests/integration/integration_clean.sh \ + --collection-root=${GITHUB_WORKSPACE}/ibm/operator_collection_sdk + env: + OCP_NAMESPACE: integration-${GITHUB_REF_NAME}-${RUNNER_OS} + ZOSCB_RELEASE: ibm-zoscb.${{ vars.ZOSCB_RELEASE }} + + molecule-tests: + name: Run Molecule Tests needs: [lint, authorize] runs-on: ${{matrix.os}} strategy: @@ -75,15 +174,17 @@ jobs: - name: Install Python Requirements uses: actions/setup-python@v4 with: - python-version: '3.10' - cache: 'pip' + python-version: "3.10" + cache: "pip" - name: Perform PIP installs run: pip install -r ${GITHUB_WORKSPACE}/ibm/operator_collection_sdk/requirements.txt - name: Perform collection installs - run: ansible-galaxy collection install ${GITHUB_WORKSPACE}/ibm/operator_collection_sdk --force - + run: | + ansible-galaxy collection install --force -r ${GITHUB_WORKSPACE}/ibm/operator_collection_sdk/requirements.yml + ansible-galaxy collection install ${GITHUB_WORKSPACE}/ibm/operator_collection_sdk --force + - name: Install oc cli uses: redhat-actions/openshift-tools-installer@v1 with: @@ -101,6 +202,6 @@ jobs: export ANSIBLE_PYTHON_INTERPRETER="$(which python)" OCP_NAMESPACE=molecule-${GITHUB_REF_NAME}-${RUNNER_OS} molecule test --all env: - OPENSHIFT_SERVER: ${{ secrets.OPENSHIFT_SERVER }} - OPENSHIFT_TOKEN: ${{ secrets.OPENSHIFT_TOKEN }} - ZOSCB_RELEASE: ibm-zoscb.${{ vars.ZOSCB_RELEASE }} \ No newline at end of file + OPENSHIFT_SERVER: ${{ secrets.OPENSHIFT_SERVER }} + OPENSHIFT_TOKEN: ${{ secrets.OPENSHIFT_TOKEN }} + ZOSCB_RELEASE: ibm-zoscb.${{ vars.ZOSCB_RELEASE }} diff --git a/.gitignore b/.gitignore index 014f58dc..398166a5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,6 @@ ibm/operator_collection_sdk/local/* examples/racf-operator/local/* .DS_Store .vscode/* -*.idea/ \ No newline at end of file +*.idea/ +__pycache__ +integration_config.yml \ No newline at end of file diff --git a/examples/racf-operator/inventories/inventory.yml b/examples/racf-operator/inventories/inventory.yml index 8e18baf3..b85571f8 100644 --- a/examples/racf-operator/inventories/inventory.yml +++ b/examples/racf-operator/inventories/inventory.yml @@ -14,5 +14,5 @@ source_system: hosts: zos_host: - ansible_host: ***HOST_REMOVED*** + ansible_host: "" ansible_user: omvsadm diff --git a/examples/racf-operator/playbooks/roles/add-zos-user/defaults/main.yml b/examples/racf-operator/playbooks/roles/add-zos-user/defaults/main.yml index d0a3d8d4..d2421928 100644 --- a/examples/racf-operator/playbooks/roles/add-zos-user/defaults/main.yml +++ b/examples/racf-operator/playbooks/roles/add-zos-user/defaults/main.yml @@ -94,7 +94,7 @@ print_pass: true ################################################################################################################## # Specifies the SMTP server to use for sending email, if sending email is desired. ################################################################################################################## -smtp_server: ***HOST_REMOVED*** +smtp_server: "" ################################################################################################################## # Specifies the SMTP port to use for sending email, if sending email is desired. diff --git a/examples/racf-operator/playbooks/roles/remove-zos-user/vars/main.yml b/examples/racf-operator/playbooks/roles/remove-zos-user/vars/main.yml index 15332de2..2c10fddb 100644 --- a/examples/racf-operator/playbooks/roles/remove-zos-user/vars/main.yml +++ b/examples/racf-operator/playbooks/roles/remove-zos-user/vars/main.yml @@ -94,7 +94,7 @@ print_pass: true ################################################################################################################## # Specifies the SMTP server to use for sending email, if sending email is desired. ################################################################################################################## -smtp_server: ***HOST_REMOVED*** +smtp_server: "" ################################################################################################################## # Specifies the SMTP port to use for sending email, if sending email is desired. diff --git a/ibm/operator_collection_sdk/galaxy.yml b/ibm/operator_collection_sdk/galaxy.yml index c66f52a5..16f2ed1e 100644 --- a/ibm/operator_collection_sdk/galaxy.yml +++ b/ibm/operator_collection_sdk/galaxy.yml @@ -71,3 +71,76 @@ build_ignore: # with 'build_ignore' # manifest: null +### REQUIRED +# The namespace of the collection. This can be a company/brand/organization or product namespace under which all +# content lives. May only contain alphanumeric lowercase characters and underscores. Namespaces cannot start with +# underscores or numbers and cannot contain consecutive underscores +namespace: ibm + +# The name of the collection. Has the same character restrictions as 'namespace' +name: operator_collection_sdk + +# The version of the collection. Must be compatible with semantic versioning +version: 2.0.0-alpha.2 + +# The path to the Markdown (.md) readme file. This path is relative to the root of the collection +readme: README.md + +# A list of the collection's content authors. Can be just the name or in the format 'Full Name (url) +# @nicks:irc/im.site#channel' +authors: +- Latrell Freeman + + +### OPTIONAL but strongly recommended +# A short summary description of the collection +description: The IBM Operator Collection SDK provides the resources and tools that are needed to develop Operator Collections against the IBM® z/OS® Cloud Broker as part of the IBM Z® and Cloud Modernization Stack. + +# The path to the license file for the collection. This path is relative to the root of the collection. This key is +# mutually exclusive with 'license' +license_file: LICENSE + +# A list of tags you want to associate with the collection for indexing/searching. A tag name has the same character +# requirements as 'namespace' and 'name' +tags: + - ibm + - operator_collection + - operator_collection_sdk + - zos + - z_os + - z + +# Collections that this collection requires to be installed for it to be usable. The key of the dict is the +# collection label 'namespace.name'. The value is a version range +# L(specifiers,https://python-semanticversion.readthedocs.io/en/latest/#requirement-specification). Multiple version +# range specifiers can be set and are separated by ',' +dependencies: {} + +# The URL of the originating SCM repository +repository: https://github.com/IBM/operator-collection-sdk + +# The URL to any online docs +documentation: https://github.com/IBM/operator-collection-sdk/blob/main/ibm/operator_collection_sdk/README.md + +# The URL to the homepage of the collection/project +homepage: https://github.com/IBM/operator-collection-sdk/blob/main/ibm/operator_collection_sdk + +# The URL to the collection issue tracker +issues: https://github.com/IBM/operator-collection-sdk/issues + +# A list of file glob-like patterns used to filter any files or directories that should not be included in the build +# artifact. A pattern is matched from the relative path of the file or directory of the collection directory. This +# uses 'fnmatch' to match the files or directories. Some directories and files like 'galaxy.yml', '*.pyc', '*.retry', +# and '.git' are always filtered. Mutually exclusive with 'manifest' +build_ignore: + - .gitignore + - playbooks/molecule + - ansible_venv + +# A dict controlling use of manifest directives used in building the collection artifact. The key 'directives' is a +# list of MANIFEST.in style +# L(directives,https://packaging.python.org/en/latest/guides/using-manifest-in/#manifest-in-commands). The key +# 'omit_default_directives' is a boolean that controls whether the default directives are used. Mutually exclusive +# with 'build_ignore' +# manifest: null + diff --git a/ibm/operator_collection_sdk/playbooks/molecule/cluster_clean.yml b/ibm/operator_collection_sdk/playbooks/molecule/cluster_clean.yml index d0c3b097..56c7666e 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/cluster_clean.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/cluster_clean.yml @@ -5,10 +5,15 @@ --- - name: Clean Test Environment - hosts: all + hosts: localhost connection: local - gather_facts: false + gather_facts: false tasks: + - name: Install dependency # necessary for gh-actions use + pip: + name: + - kubernetes + - name: Get SubOperatorConfigs kubernetes.core.k8s_info: api_version: zoscb.ibm.com/v2beta2 diff --git a/ibm/operator_collection_sdk/playbooks/molecule/cluster_setup.yml b/ibm/operator_collection_sdk/playbooks/molecule/cluster_setup.yml index ffa71f58..320d7cf9 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/cluster_setup.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/cluster_setup.yml @@ -5,10 +5,15 @@ --- - name: Test Environment Setup - hosts: all + hosts: localhost connection: local - gather_facts: false + gather_facts: false tasks: + - name: Install dependency # necessary for gh-actions use + pip: + name: + - kubernetes + - name: Create Namespace kubernetes.core.k8s: state: present diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_offline_requirements/destroy.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_offline_requirements/destroy.yml index 3dbff54e..566b310e 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_offline_requirements/destroy.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_offline_requirements/destroy.yml @@ -15,4 +15,3 @@ ansible.builtin.file: path: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../examples/racf-operator-test" state: absent - diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_offline_requirements/verify.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_offline_requirements/verify.yml index 246805a7..9b2933e7 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_offline_requirements/verify.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_offline_requirements/verify.yml @@ -55,7 +55,7 @@ - name: Assert that requirements.yml contains correct ansible requirements ansible.builtin.assert: that: - - "zos_core_filename in requirementsyml.collections[0].name" + - "zos_core_filename in requirementsyml.collections[0].name" - name: Search for wheelhouse directory ansible.builtin.find: diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_offline_requirements_manual_downloads/destroy.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_offline_requirements_manual_downloads/destroy.yml index 3dbff54e..566b310e 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_offline_requirements_manual_downloads/destroy.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_offline_requirements_manual_downloads/destroy.yml @@ -15,4 +15,3 @@ ansible.builtin.file: path: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../examples/racf-operator-test" state: absent - diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_offline_requirements_manual_downloads/verify.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_offline_requirements_manual_downloads/verify.yml index cb477137..52bb6010 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_offline_requirements_manual_downloads/verify.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_offline_requirements_manual_downloads/verify.yml @@ -55,6 +55,6 @@ - name: Assert that requirements.yml contains correct ansible requirements ansible.builtin.assert: that: - - "zos_core_filename in requirementsyml.collections[0].name" + - "zos_core_filename in requirementsyml.collections[0].name" diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_operator_config/verify.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_operator_config/verify.yml index 10896b0a..9c92ee39 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_operator_config/verify.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_operator_config/verify.yml @@ -18,7 +18,7 @@ - name: Assert that the galaxy.yml file exists ansible.builtin.assert: that: - - galaxyyml.matched == 1 + - galaxyyml.matched == 1 - name: Read galaxy.yml ansible.builtin.set_fact: @@ -33,7 +33,7 @@ - name: Assert that the operator-config.yml file exists ansible.builtin.assert: that: - - operatorconfig.matched == 1 + - operatorconfig.matched == 1 - name: Read operator-config ansible.builtin.set_fact: @@ -42,18 +42,18 @@ - name: Assert that operator-config.yml contains correct values ansible.builtin.assert: that: - - operatorconfigdata.description == galaxydata.description - - operatorconfigdata.version == galaxydata.version - - operatorconfigdata.displayName is defined - - operatorconfigdata.domain == "{{ collection_namespace | lower | replace('_','-') }}" - - operatorconfigdata.name == "{{ collection_name | lower | replace('_','-') }}" - - operatorconfigdata.resources[0].description is defined - - operatorconfigdata.resources[0].displayName is defined - - operatorconfigdata.resources[0].kind is defined - - operatorconfigdata.resources[0].playbook == 'playbooks/playbook.yml' - - operatorconfigdata.resources[0].vars[0].description is defined - - operatorconfigdata.resources[0].vars[0].displayName is defined - - operatorconfigdata.resources[0].vars[0].name is defined - - operatorconfigdata.resources[0].vars[0].type is defined + - operatorconfigdata.description == galaxydata.description + - operatorconfigdata.version == galaxydata.version + - operatorconfigdata.displayName is defined + - operatorconfigdata.domain == "{{ collection_namespace | lower | replace('_','-') }}" + - operatorconfigdata.name == "{{ collection_name | lower | replace('_','-') }}" + - operatorconfigdata.resources[0].description is defined + - operatorconfigdata.resources[0].displayName is defined + - operatorconfigdata.resources[0].kind is defined + - operatorconfigdata.resources[0].playbook == 'playbooks/playbook.yml' + - operatorconfigdata.resources[0].vars[0].description is defined + - operatorconfigdata.resources[0].vars[0].displayName is defined + - operatorconfigdata.resources[0].vars[0].name is defined + - operatorconfigdata.resources[0].vars[0].type is defined diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/converge.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/converge.yml index 8331c616..e0f99af7 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/converge.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/converge.yml @@ -4,10 +4,101 @@ # --- -- name: Set up test environment - import_playbook: ../cluster_setup.yml - - name: Converge - import_playbook: ../../create_operator.yml + hosts: all + connection: local + gather_facts: false + vars: + ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" + + tasks: + - name: Create Namespace + kubernetes.core.k8s: + state: present + definition: + kind: Namespace + metadata: + name: "{{ ocpnamespace }}" + + - name: Create OperatorGroup + kubernetes.core.k8s: + state: present + definition: + apiVersion: operators.coreos.com/v1 + kind: OperatorGroup + metadata: + name: "{{ ocpnamespace }}" + namespace: "{{ ocpnamespace }}" + spec: + targetNamespaces: + - "{{ ocpnamespace }}" + upgradeStrategy: Default + + - name: Create Subscripton + kubernetes.core.k8s: + state: present + definition: + apiVersion: operators.coreos.com/v1alpha1 + kind: Subscription + metadata: + name: "{{ subscription_name }}" + namespace: "{{ ocpnamespace }}" + spec: + channel: v2.2 + installPlanApproval: Automatic + name: ibm-zoscb + source: ibm-operator-catalog + sourceNamespace: openshift-marketplace + startingCSV: "{{ zoscb_release }}" + + - name: Validate Subscription installed successfully + kubernetes.core.k8s_info: + api_version: operators.coreos.com/v1alpha1 + kind: Subscription + name: "{{ subscription_name }}" + namespace: "{{ ocpnamespace }}" + register: subscription_results + until: "subscription_results.resources[0].status.installedCSV is defined and subscription_results.resources[0].status.currentCSV" + retries: 30 + delay: 5 + + - name: Validate CSV installed successfully + kubernetes.core.k8s_info: + api_version: operators.coreos.com/v1alpha1 + kind: ClusterServiceVersion + name: "{{ subscription_results.resources[0].status.installedCSV }}" + namespace: "{{ ocpnamespace }}" + register: csv_results + until: "csv_results.resources[0].status.phase is defined and csv_results.resources[0].status.phase == 'Succeeded'" + retries: 30 + delay: 5 + + - name: Create ZosCloudBroker + ibm.operator_collection_sdk.oc_zoscloudbroker: + state: present + namespace: "{{ ocpnamespace }}" + accept_license: true + multi_namespace: true + log_level: trace + storage: + configure: false + enabled: false + storage_size: 5Gi + volume_mode: Filesystem + + - name: Validate ZosCloudBroker installed successfully + kubernetes.core.k8s_info: + api_version: zoscb.ibm.com/v2beta1 + kind: ZosCloudBroker + name: "{{ zoscloudbroker_name }}" + namespace: "{{ ocpnamespace }}" + register: zoscb_results + until: "zoscb_results.resources[0].status.phase == 'Successful'" + retries: 30 + delay: 5 + + +- import_playbook: ../../create_operator.yml vars: - filepath: "{{ operator_path }}" + filepath: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../examples/racf-operator" + ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/destroy.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/destroy.yml index 7b493920..3132bf3d 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/destroy.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/destroy.yml @@ -8,16 +8,87 @@ import_playbook: ../../delete_operator.yml vars: filepath: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../examples/racf-operator" - -- name: Clean test environment - import_playbook: ../cluster_clean.yml - + ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" - name: Destroy hosts: localhost connection: local gather_facts: false no_log: "{{ molecule_no_log }}" + vars: + ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" + tasks: + - name: Get SubOperatorConfigs + kubernetes.core.k8s_info: + api_version: zoscb.ibm.com/v2beta2 + kind: SubOperatorConfig + namespace: "{{ target_namespace }}" + register: soc_results + + - name: Remove Orphaned SubOperatorConfigs + kubernetes.core.k8s_json_patch: + api_version: zoscb.ibm.com/v2beta2 + kind: SubOperatorConfig + namespace: "{{ target_namespace }}" + name: "{{ item.metadata.name }}" + patch: + - op: replace + path: /metadata/finalizers + value: [] + when: soc_results.resources | length > 0 + with_items: "{{ soc_results.resources }}" + + - name: Delete ZosEndpoint + kubernetes.core.k8s: + state: absent + api_version: zoscb.ibm.com/v2beta2 + kind: ZosEndpoint + name: "{{ zosendpoint_name }}" + namespace: "{{ ocpnamespace }}" + wait: true + wait_sleep: 5 + wait_timeout: 140 + + - name: Delete ZosCloudBoker + kubernetes.core.k8s: + state: absent + api_version: zoscb.ibm.com/v2beta1 + kind: ZosCloudBroker + name: "{{ zoscloudbroker_name }}" + namespace: "{{ ocpnamespace }}" + wait: true + wait_sleep: 5 + wait_timeout: 140 + + - name: Delete Subscripton + kubernetes.core.k8s: + state: absent + api_version: operators.coreos.com/v1alpha1 + kind: Subscription + name: "{{ subscription_name }}" + namespace: "{{ ocpnamespace }}" + wait: true + wait_sleep: 5 + wait_timeout: 140 + + - name: Delete OperatorGroup + kubernetes.core.k8s: + state: absent + api_version: operators.coreos.com/v1 + kind: OperatorGroup + name: "{{ ocpnamespace }}" + namespace: "{{ ocpnamespace }}" + + - name: Delete Namespace + kubernetes.core.k8s: + state: absent + kind: Namespace + name: "{{ ocpnamespace }}" + wait: true + wait_sleep: 5 + wait_timeout: 140 + ignore_errors: true + - name: Remove local build ansible.builtin.file: path: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../examples/racf-operator/local" diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/molecule.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/molecule.yml index 798df40d..c976d82e 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/molecule.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/molecule.yml @@ -15,8 +15,6 @@ provisioner: config_options: defaults: jinja2_native: true - playbooks: - cleanup: cleanup.yml ## extra-vars needed to bypass vars_prompts ansible_args: @@ -28,8 +26,7 @@ provisioner: collection_namespace: ibm subscription_name: ibm-zoscb zoscloudbroker_name: zoscloudbroker - ocpnamespace: "{{ '${OCP_NAMESPACE:-molecule}' | lower | regex_replace('[^-a-zA-Z0-9]','-') }}" - operator_path: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../examples/racf-operator" + ocpNamespace: ${OCP_NAMESPACE:-molecule} zosendpoint_name: ibmcloud-vm openshift_token: ${OPENSHIFT_TOKEN} openshift_server: ${OPENSHIFT_SERVER} diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/prepare.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/prepare.yml index 1c835d53..509f6e25 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/prepare.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/prepare.yml @@ -8,6 +8,9 @@ hosts: all connection: local gather_facts: false + vars: + ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" + tasks: - name: Validate OCP cluster authorization ansible.builtin.command: oc project diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/verify.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/verify.yml index 5e814f59..598821e3 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/verify.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/verify.yml @@ -8,6 +8,9 @@ hosts: all connection: local gather_facts: false + vars: + ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" + tasks: - name: Validate ZosEndpoint kubernetes.core.k8s_info: @@ -20,9 +23,9 @@ - name: Assert ZosEndpoint configuration ansible.builtin.assert: that: - - zosendpoint_results.resources[0].status.phase == 'Successful' - - zosendpoint_results.resources[0].status.suboperatorconfigs | length == 1 - - zosendpoint_results.resources[0].spec.endpointType == "local" + - zosendpoint_results.resources[0].status.phase == 'Successful' + - zosendpoint_results.resources[0].status.suboperatorconfigs | length == 1 + - zosendpoint_results.resources[0].spec.endpointType == "local" - name: Validate SubOperatorConfig kubernetes.core.k8s_info: @@ -35,15 +38,15 @@ - name: Assert SubOperatorConfig configuration ansible.builtin.assert: that: - - suboperatorconfig_results.resources[0].spec.credentialType == 'shared' - - suboperatorconfig_results.resources[0].spec.mapping[0].namespace == '{{ ocpnamespace }}' - - suboperatorconfig_results.resources[0].spec.mapping[0].zosendpoints[0].name == '{{ zosendpoint_name }}' - - suboperatorconfig_results.resources[0].spec.mapping[0].zosendpoints[0].credentialName is undefined - - suboperatorconfig_results.resources[0].spec.operatorCollection is defined - - suboperatorconfig_results.resources[0].status.phase == 'Successful' - - suboperatorconfig_results.resources[0].status.clusterserviceversion is defined - - suboperatorconfig_results.resources[0].status.customresourcedefinition | length > 0 - - suboperatorconfig_results.resources[0].status.packages is defined + - suboperatorconfig_results.resources[0].spec.credentialType == 'shared' + - suboperatorconfig_results.resources[0].spec.mapping[0].namespace == '{{ ocpnamespace }}' + - suboperatorconfig_results.resources[0].spec.mapping[0].zosendpoints[0].name == '{{ zosendpoint_name }}' + - suboperatorconfig_results.resources[0].spec.mapping[0].zosendpoints[0].credentialName is undefined + - suboperatorconfig_results.resources[0].spec.operatorCollection is defined + - suboperatorconfig_results.resources[0].status.phase == 'Successful' + - suboperatorconfig_results.resources[0].status.clusterserviceversion is defined + - suboperatorconfig_results.resources[0].status.customresourcedefinition | length > 0 + - suboperatorconfig_results.resources[0].status.packages is defined - name: Validate OperatorCollection kubernetes.core.k8s_info: @@ -56,10 +59,10 @@ - name: Assert OperatorCollection configuration ansible.builtin.assert: that: - - operatorcollection_results.resources[0].spec.skipSignatureVerification is true - - operatorcollection_results.resources[0].status.config.collectionPath is defined - - operatorcollection_results.resources[0].status.phase == 'Successful' - - operatorcollection_results.resources[0].status.subOperatorConfigMappingStatus | length == 1 + - operatorcollection_results.resources[0].spec.skipSignatureVerification is true + - operatorcollection_results.resources[0].status.config.collectionPath is defined + - operatorcollection_results.resources[0].status.phase == 'Successful' + - operatorcollection_results.resources[0].status.subOperatorConfigMappingStatus | length == 1 - name: Validate CSV kubernetes.core.k8s_info: @@ -76,4 +79,4 @@ - name: Assert CSV configuration ansible.builtin.assert: that: - - csv_results.resources[0].status.phase == 'Succeeded' \ No newline at end of file + - csv_results.resources[0].status.phase == 'Succeeded' \ No newline at end of file diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/converge.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/converge.yml index 70c4a97d..b1b738e2 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/converge.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/converge.yml @@ -8,19 +8,111 @@ hosts: all connection: local gather_facts: false + vars: + ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" + + tasks: + - name: Create Namespace + kubernetes.core.k8s: + state: present + definition: + kind: Namespace + metadata: + name: "{{ ocpnamespace }}" + + - name: Create OperatorGroup + kubernetes.core.k8s: + state: present + definition: + apiVersion: operators.coreos.com/v1 + kind: OperatorGroup + metadata: + name: "{{ ocpnamespace }}" + namespace: "{{ ocpnamespace }}" + spec: + targetNamespaces: + - "{{ ocpnamespace }}" + upgradeStrategy: Default + + - name: Create Subscripton + kubernetes.core.k8s: + state: present + definition: + apiVersion: operators.coreos.com/v1alpha1 + kind: Subscription + metadata: + name: "{{ subscription_name }}" + namespace: "{{ ocpnamespace }}" + spec: + channel: v2.2 + installPlanApproval: Automatic + name: ibm-zoscb + source: ibm-operator-catalog + sourceNamespace: openshift-marketplace + startingCSV: "{{ zoscb_release }}" + + - name: Validate Subscription installed successfully + kubernetes.core.k8s_info: + api_version: operators.coreos.com/v1alpha1 + kind: Subscription + name: "{{ subscription_name }}" + namespace: "{{ ocpnamespace }}" + register: subscription_results + until: "subscription_results.resources[0].status.installedCSV is defined and subscription_results.resources[0].status.currentCSV" + retries: 30 + delay: 5 + + - name: Validate CSV installed successfully + kubernetes.core.k8s_info: + api_version: operators.coreos.com/v1alpha1 + kind: ClusterServiceVersion + name: "{{ subscription_results.resources[0].status.installedCSV }}" + namespace: "{{ ocpnamespace }}" + register: csv_results + until: "csv_results.resources[0].status.phase is defined and csv_results.resources[0].status.phase == 'Succeeded'" + retries: 30 + delay: 5 + + - name: Create ZosCloudBroker + ibm.operator_collection_sdk.oc_zoscloudbroker: + state: present + namespace: "{{ ocpnamespace }}" + accept_license: true + multi_namespace: true + log_level: trace + storage: + configure: false + enabled: false + storage_size: 5Gi + volume_mode: Filesystem + + - name: Validate ZosCloudBroker installed successfully + kubernetes.core.k8s_info: + api_version: zoscb.ibm.com/v2beta1 + kind: ZosCloudBroker + name: "{{ zoscloudbroker_name }}" + namespace: "{{ ocpnamespace }}" + register: zoscb_results + until: "zoscb_results.resources[0].status.phase == 'Successful'" + retries: 30 + delay: 5 -- import_playbook: ../cluster_setup.yml - import_playbook: ../../create_operator.yml vars: - filepath: "{{ operator_path }}" + filepath: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../examples/racf-operator" + ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" - import_playbook: ../../create_credential_secret.yml + vars: + ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" - import_playbook: ../../redeploy_operator.yml vars: - filepath: "{{ operator_path }}" + filepath: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../examples/racf-operator" + ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" - import_playbook: ../../redeploy_collection.yml vars: - filepath: "{{ operator_path }}" \ No newline at end of file + filepath: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../examples/racf-operator" + ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" \ No newline at end of file diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/destroy.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/destroy.yml index 7b493920..4aa3537c 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/destroy.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/destroy.yml @@ -8,16 +8,97 @@ import_playbook: ../../delete_operator.yml vars: filepath: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../examples/racf-operator" - -- name: Clean test environment - import_playbook: ../cluster_clean.yml - + ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" - name: Destroy hosts: localhost connection: local gather_facts: false no_log: "{{ molecule_no_log }}" + vars: + ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" + tasks: + - name: Get SubOperatorConfigs + kubernetes.core.k8s_info: + api_version: zoscb.ibm.com/v2beta2 + kind: SubOperatorConfig + namespace: "{{ target_namespace }}" + register: soc_results + + - name: Remove Orphaned SubOperatorConfigs + kubernetes.core.k8s_json_patch: + api_version: zoscb.ibm.com/v2beta2 + kind: SubOperatorConfig + namespace: "{{ target_namespace }}" + name: "{{ item.metadata.name }}" + patch: + - op: replace + path: /metadata/finalizers + value: [] + when: soc_results.resources | length > 0 + with_items: "{{ soc_results.resources }}" + + - name: Delete test secret + kubernetes.core.k8s: + state: absent + kind: secret + name: "{{ secret_name }}" + namespace: "{{ ocpnamespace }}" + wait: true + wait_sleep: 5 + wait_timeout: 140 + + - name: Delete ZosEndpoint + kubernetes.core.k8s: + state: absent + api_version: zoscb.ibm.com/v2beta2 + kind: ZosEndpoint + name: "{{ zosendpoint_name }}" + namespace: "{{ ocpnamespace }}" + wait: true + wait_sleep: 5 + wait_timeout: 140 + + - name: Delete ZosCloudBoker + kubernetes.core.k8s: + state: absent + api_version: zoscb.ibm.com/v2beta1 + kind: ZosCloudBroker + name: "{{ zoscloudbroker_name }}" + namespace: "{{ ocpnamespace }}" + wait: true + wait_sleep: 5 + wait_timeout: 140 + + - name: Delete Subscripton + kubernetes.core.k8s: + state: absent + api_version: operators.coreos.com/v1alpha1 + kind: Subscription + name: "{{ subscription_name }}" + namespace: "{{ ocpnamespace }}" + wait: true + wait_sleep: 5 + wait_timeout: 140 + + - name: Delete OperatorGroup + kubernetes.core.k8s: + state: absent + api_version: operators.coreos.com/v1 + kind: OperatorGroup + name: "{{ ocpnamespace }}" + namespace: "{{ ocpnamespace }}" + + - name: Delete Namespace + kubernetes.core.k8s: + state: absent + kind: Namespace + name: "{{ ocpnamespace }}" + wait: true + wait_sleep: 5 + wait_timeout: 140 + ignore_errors: true + - name: Remove local build ansible.builtin.file: path: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../examples/racf-operator/local" diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/molecule.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/molecule.yml index be2f34ea..ec785725 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/molecule.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/molecule.yml @@ -15,8 +15,6 @@ provisioner: config_options: defaults: jinja2_native: true - playbooks: - cleanup: cleanup.yml ## extra-vars needed to bypass vars_prompts ansible_args: @@ -28,8 +26,7 @@ provisioner: collection_namespace: ibm subscription_name: ibm-zoscb zoscloudbroker_name: zoscloudbroker - ocpnamespace: "{{ '${OCP_NAMESPACE:-molecule}' | lower | regex_replace('[^-a-zA-Z0-9]','-') }}" - operator_path: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../examples/racf-operator" + ocpNamespace: ${OCP_NAMESPACE:-molecule} zosendpoint_name: ibmcloud-vm secret_name: "test-secret" openshift_token: ${OPENSHIFT_TOKEN} diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/prepare.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/prepare.yml index 1c835d53..509f6e25 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/prepare.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/prepare.yml @@ -8,6 +8,9 @@ hosts: all connection: local gather_facts: false + vars: + ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" + tasks: - name: Validate OCP cluster authorization ansible.builtin.command: oc project diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/verify.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/verify.yml index d21e2811..a50220c5 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/verify.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/verify.yml @@ -8,6 +8,9 @@ hosts: all connection: local gather_facts: false + vars: + ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" + tasks: - name: Validate ZosEndpoint kubernetes.core.k8s_info: @@ -20,9 +23,9 @@ - name: Assert ZosEndpoint configuration ansible.builtin.assert: that: - - zosendpoint_results.resources[0].status.phase == 'Successful' - - zosendpoint_results.resources[0].status.suboperatorconfigs | length == 1 - - zosendpoint_results.resources[0].spec.endpointType == "remote" + - zosendpoint_results.resources[0].status.phase == 'Successful' + - zosendpoint_results.resources[0].status.suboperatorconfigs | length == 1 + - zosendpoint_results.resources[0].spec.endpointType == "remote" - name: Validate SubOperatorConfig kubernetes.core.k8s_info: @@ -35,15 +38,15 @@ - name: Assert SubOperatorConfig configuration ansible.builtin.assert: that: - - suboperatorconfig_results.resources[0].spec.credentialType == 'personal' - - suboperatorconfig_results.resources[0].spec.mapping[0].namespace == '{{ ocpnamespace }}' - - suboperatorconfig_results.resources[0].spec.mapping[0].zosendpoints[0].name == '{{ zosendpoint_name }}' - - suboperatorconfig_results.resources[0].spec.mapping[0].zosendpoints[0].credentialName is undefined - - suboperatorconfig_results.resources[0].spec.operatorCollection is defined - - suboperatorconfig_results.resources[0].status.phase == 'Successful' - - suboperatorconfig_results.resources[0].status.clusterserviceversion is defined - - suboperatorconfig_results.resources[0].status.customresourcedefinition | length > 0 - - suboperatorconfig_results.resources[0].status.packages is defined + - suboperatorconfig_results.resources[0].spec.credentialType == 'personal' + - suboperatorconfig_results.resources[0].spec.mapping[0].namespace == '{{ ocpnamespace }}' + - suboperatorconfig_results.resources[0].spec.mapping[0].zosendpoints[0].name == '{{ zosendpoint_name }}' + - suboperatorconfig_results.resources[0].spec.mapping[0].zosendpoints[0].credentialName is undefined + - suboperatorconfig_results.resources[0].spec.operatorCollection is defined + - suboperatorconfig_results.resources[0].status.phase == 'Successful' + - suboperatorconfig_results.resources[0].status.clusterserviceversion is defined + - suboperatorconfig_results.resources[0].status.customresourcedefinition | length > 0 + - suboperatorconfig_results.resources[0].status.packages is defined - name: Validate OperatorCollection kubernetes.core.k8s_info: @@ -56,10 +59,10 @@ - name: Assert OperatorCollection configuration ansible.builtin.assert: that: - - operatorcollection_results.resources[0].spec.skipSignatureVerification is true - - operatorcollection_results.resources[0].status.config.collectionPath is defined - - operatorcollection_results.resources[0].status.phase == 'Successful' - - operatorcollection_results.resources[0].status.subOperatorConfigMappingStatus | length == 1 + - operatorcollection_results.resources[0].spec.skipSignatureVerification is true + - operatorcollection_results.resources[0].status.config.collectionPath is defined + - operatorcollection_results.resources[0].status.phase == 'Successful' + - operatorcollection_results.resources[0].status.subOperatorConfigMappingStatus | length == 1 - name: Validate CSV kubernetes.core.k8s_info: @@ -76,7 +79,7 @@ - name: Assert CSV configuration ansible.builtin.assert: that: - - csv_results.resources[0].status.phase == 'Succeeded' + - csv_results.resources[0].status.phase == 'Succeeded' - name: Validate default secret kubernetes.core.k8s_info: @@ -93,7 +96,7 @@ - name: Assert default secret ansible.builtin.assert: that: - - default_secret_results.resources[0].data is defined - - default_secret_results.resources[0].type == "Opaque" - - default_secret_results.resources[0].data.ssh_key != "" - - default_secret_results.resources[0].data.username != "" \ No newline at end of file + - default_secret_results.resources[0].data is defined + - default_secret_results.resources[0].type == "Opaque" + - default_secret_results.resources[0].data.ssh_key != "" + - default_secret_results.resources[0].data.username != "" \ No newline at end of file diff --git a/ibm/operator_collection_sdk/playbooks/molecule/init_collection/destroy.yml b/ibm/operator_collection_sdk/playbooks/molecule/init_collection/destroy.yml index 80cf5bed..fbd3544b 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/init_collection/destroy.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/init_collection/destroy.yml @@ -15,4 +15,3 @@ ansible.builtin.file: path: "{{ lookup('env', 'PWD') }}/{{ collection_namespace | lower | replace('-','_') }}" state: absent - diff --git a/ibm/operator_collection_sdk/playbooks/molecule/init_collection/verify.yml b/ibm/operator_collection_sdk/playbooks/molecule/init_collection/verify.yml index b1cb3b72..ba535734 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/init_collection/verify.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/init_collection/verify.yml @@ -40,8 +40,8 @@ - name: Assert that requirements.yml contains correct ansible requirements ansible.builtin.assert: that: - - "'operator_sdk.util' in requirementsyml.collections[0].name" - - "'kubernetes.core' in requirementsyml.collections[1].name" + - "'operator_sdk.util' in requirementsyml.collections[0].name" + - "'kubernetes.core' in requirementsyml.collections[1].name" - name: Find playbooks directory ansible.builtin.find: @@ -64,8 +64,8 @@ - name: Assert that requirements.yml contains correct ansible requirements ansible.builtin.assert: that: - - "'all' in playbookyml[0].hosts" - - "'vars/my_vars.yml' in playbookyml[0].vars_files[0]" + - "'all' in playbookyml[0].hosts" + - "'vars/my_vars.yml' in playbookyml[0].vars_files[0]" - name: Find roles directory ansible.builtin.find: @@ -75,7 +75,7 @@ - name: Assert that the roles directory exists ansible.builtin.assert: that: - - roles_path.warnings is not defined + - roles_path.warnings is not defined - name: Find galaxy.yml file ansible.builtin.find: @@ -86,7 +86,7 @@ - name: Assert that the galaxy.yml file exists ansible.builtin.assert: that: - - galaxyyml.matched == 1 + - galaxyyml.matched == 1 - name: Read galaxy.yml ansible.builtin.set_fact: @@ -101,7 +101,7 @@ - name: Assert that the operator-config.yml file exists ansible.builtin.assert: that: - - operatorconfig.matched == 1 + - operatorconfig.matched == 1 - name: Read operator-config ansible.builtin.set_fact: @@ -110,19 +110,19 @@ - name: Assert that operator-config.yml contains correct values ansible.builtin.assert: that: - - operatorconfigdata.description == galaxydata.description - - operatorconfigdata.version == galaxydata.version - - operatorconfigdata.displayName is defined - - operatorconfigdata.domain == "{{ collection_namespace | lower | replace('_','-') }}" - - operatorconfigdata.name == "{{ collection_name | lower | replace('_','-') }}" - - operatorconfigdata.resources[0].description is defined - - operatorconfigdata.resources[0].displayName is defined - - operatorconfigdata.resources[0].kind is defined - - operatorconfigdata.resources[0].playbook == 'playbooks/playbook.yml' - - operatorconfigdata.resources[0].vars[0].description is defined - - operatorconfigdata.resources[0].vars[0].displayName is defined - - operatorconfigdata.resources[0].vars[0].name is defined - - operatorconfigdata.resources[0].vars[0].type is defined + - operatorconfigdata.description == galaxydata.description + - operatorconfigdata.version == galaxydata.version + - operatorconfigdata.displayName is defined + - operatorconfigdata.domain == "{{ collection_namespace | lower | replace('_','-') }}" + - operatorconfigdata.name == "{{ collection_name | lower | replace('_','-') }}" + - operatorconfigdata.resources[0].description is defined + - operatorconfigdata.resources[0].displayName is defined + - operatorconfigdata.resources[0].kind is defined + - operatorconfigdata.resources[0].playbook == 'playbooks/playbook.yml' + - operatorconfigdata.resources[0].vars[0].description is defined + - operatorconfigdata.resources[0].vars[0].displayName is defined + - operatorconfigdata.resources[0].vars[0].name is defined + - operatorconfigdata.resources[0].vars[0].type is defined - name: Find ./.vscode/extensions.json file" ansible.builtin.stat: @@ -140,6 +140,6 @@ - name: Assert that requirements.yml contains correct ansible requirements ansible.builtin.assert: that: - - "'recommendations' in extensionsjson" - - "'ibm.operator-collection-sdk' in extensionsjson.recommendations" - - "'redhat.ansible' in extensionsjson.recommendations" + - "'recommendations' in extensionsjson" + - "'ibm.operator-collection-sdk' in extensionsjson.recommendations" + - "'redhat.ansible' in extensionsjson.recommendations" diff --git a/ibm/operator_collection_sdk/playbooks/molecule/init_collection_offline/destroy.yml b/ibm/operator_collection_sdk/playbooks/molecule/init_collection_offline/destroy.yml index 80cf5bed..fbd3544b 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/init_collection_offline/destroy.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/init_collection_offline/destroy.yml @@ -15,4 +15,3 @@ ansible.builtin.file: path: "{{ lookup('env', 'PWD') }}/{{ collection_namespace | lower | replace('-','_') }}" state: absent - diff --git a/ibm/operator_collection_sdk/playbooks/molecule/init_collection_offline/verify.yml b/ibm/operator_collection_sdk/playbooks/molecule/init_collection_offline/verify.yml index d4fac3fc..71094502 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/init_collection_offline/verify.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/init_collection_offline/verify.yml @@ -88,8 +88,8 @@ - name: Assert that requirements.yml contains correct ansible requirements ansible.builtin.assert: that: - - "'all' in playbookyml[0].hosts" - - "'vars/my_vars.yml' in playbookyml[0].vars_files[0]" + - "'all' in playbookyml[0].hosts" + - "'vars/my_vars.yml' in playbookyml[0].vars_files[0]" - name: Find roles directory ansible.builtin.find: @@ -99,7 +99,7 @@ - name: Assert that the roles directory exists ansible.builtin.assert: that: - - roles_path.warnings is not defined + - roles_path.warnings is not defined - name: Find galaxy.yml file ansible.builtin.find: @@ -110,7 +110,7 @@ - name: Assert that the galaxy.yml file exists ansible.builtin.assert: that: - - galaxyyml.matched == 1 + - galaxyyml.matched == 1 - name: Read galaxy.yml ansible.builtin.set_fact: @@ -125,7 +125,7 @@ - name: Assert that the operator-config.yml file exists ansible.builtin.assert: that: - - operatorconfig.matched == 1 + - operatorconfig.matched == 1 - name: Read operator-config ansible.builtin.set_fact: @@ -134,19 +134,19 @@ - name: Assert that operator-config.yml contains correct values ansible.builtin.assert: that: - - operatorconfigdata.description == galaxydata.description - - operatorconfigdata.version == galaxydata.version - - operatorconfigdata.displayName is defined - - operatorconfigdata.domain == "{{ collection_namespace | lower | replace('_','-') }}" - - operatorconfigdata.name == "{{ collection_name | lower | replace('_','-') }}" - - operatorconfigdata.resources[0].description is defined - - operatorconfigdata.resources[0].displayName is defined - - operatorconfigdata.resources[0].kind is defined - - operatorconfigdata.resources[0].playbook == 'playbooks/playbook.yml' - - operatorconfigdata.resources[0].vars[0].description is defined - - operatorconfigdata.resources[0].vars[0].displayName is defined - - operatorconfigdata.resources[0].vars[0].name is defined - - operatorconfigdata.resources[0].vars[0].type is defined + - operatorconfigdata.description == galaxydata.description + - operatorconfigdata.version == galaxydata.version + - operatorconfigdata.displayName is defined + - operatorconfigdata.domain == "{{ collection_namespace | lower | replace('_','-') }}" + - operatorconfigdata.name == "{{ collection_name | lower | replace('_','-') }}" + - operatorconfigdata.resources[0].description is defined + - operatorconfigdata.resources[0].displayName is defined + - operatorconfigdata.resources[0].kind is defined + - operatorconfigdata.resources[0].playbook == 'playbooks/playbook.yml' + - operatorconfigdata.resources[0].vars[0].description is defined + - operatorconfigdata.resources[0].vars[0].displayName is defined + - operatorconfigdata.resources[0].vars[0].name is defined + - operatorconfigdata.resources[0].vars[0].type is defined - name: Find ./.vscode/extensions.json file" ansible.builtin.stat: @@ -164,6 +164,6 @@ - name: Assert that requirements.yml contains correct ansible requirements ansible.builtin.assert: that: - - "'recommendations' in extensionsjson" - - "'ibm.operator-collection-sdk' in extensionsjson.recommendations" - - "'redhat.ansible' in extensionsjson.recommendations" + - "'recommendations' in extensionsjson" + - "'ibm.operator-collection-sdk' in extensionsjson.recommendations" + - "'redhat.ansible' in extensionsjson.recommendations" diff --git a/ibm/operator_collection_sdk/playbooks/redeploy_operator.yml b/ibm/operator_collection_sdk/playbooks/redeploy_operator.yml index c7d4ddc3..6990fe9d 100644 --- a/ibm/operator_collection_sdk/playbooks/redeploy_operator.yml +++ b/ibm/operator_collection_sdk/playbooks/redeploy_operator.yml @@ -82,7 +82,6 @@ wait: true wait_sleep: 5 wait_timeout: 140 - ignore_errors: true - name: Set OperatorCollection name ansible.builtin.set_fact: diff --git a/ibm/operator_collection_sdk/playbooks/templates/zoscloudbroker.yml.j2 b/ibm/operator_collection_sdk/playbooks/templates/zoscloudbroker.yml.j2 new file mode 100644 index 00000000..210586e1 --- /dev/null +++ b/ibm/operator_collection_sdk/playbooks/templates/zoscloudbroker.yml.j2 @@ -0,0 +1,37 @@ +{# templates/zoscloudbroker.yml.j2 #} + +apiVersion: zoscb.ibm.com/v2beta1 +kind: ZosCloudBroker +metadata: + name: {{name}} + namespace: {{namespace}} + labels: {{ labels }} +spec: + catalogResources: {} + galaxyConfig: + enabled: {{ ansible_galaxy_configuration.enabled }} + galaxyURL: {{ ansible_galaxy_configuration.url }} + license: + accept: {{ accept_license }} + logLevel: {{ log_level }} + managerResources: {} + multiNamespace: {{ multi_namespace_suboperators }} + storage: + {% if storage.configure %} + accessModes: ReadWriteMany + volumeMode: Filesystem + configure: true + enabled: false + size: {{ storage.storage_size }} + storageClassName: {{ storage.storage_class }} + {% else %} + {% if storage.enabled %} + configure: false + enabled: true + pvc: {{ storage.persistent_volume_claim }} + {% else %} + configure: false + enabled: false + {% endif %} + {% endif %} + uiResources: {} \ No newline at end of file diff --git a/ibm/operator_collection_sdk/plugins/doc_fragments/__init__.py b/ibm/operator_collection_sdk/plugins/doc_fragments/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/ibm/operator_collection_sdk/plugins/module_utils/__init__.py b/ibm/operator_collection_sdk/plugins/module_utils/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/ibm/operator_collection_sdk/plugins/module_utils/util.py b/ibm/operator_collection_sdk/plugins/module_utils/util.py new file mode 100644 index 00000000..e2778564 --- /dev/null +++ b/ibm/operator_collection_sdk/plugins/module_utils/util.py @@ -0,0 +1,52 @@ +# (c) Copyright IBM Corp. 2024 +# Apache License, Version 2.0 (see https://opensource.org/licenses/Apache-2.0) +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +import os +import subprocess +from re import findall +from json import loads + + +def get_collection_root_path(): + error = None + collections_root_path = None + + # check defaults + default_paths = [ + "/usr/share/ansible/collections/ansible_collections", + os.path.expanduser("~/.ansible/collections/ansible_collections") + ] + for path in default_paths: + candidate = os.path.join(path, "ibm", "operator_collection_sdk") + if os.path.exists(candidate): + collections_root_path = candidate + break + + # attempt to derive path from shell + if collections_root_path is None: + try: + command = ["ansible-config dump"] + stdout = subprocess.run(command, shell=True, text=True, capture_output=True, check=True).stdout + + # filter output for COLLECTIONS_PATHS = [*] + match = findall(r"COLLECTIONS_PATHS[^=]*= [^\]]*\]", stdout) + del stdout + + if len(match) > 0: + string_paths = match[0].split("=")[1].strip() + + # valid json must be double quoted for json.loads + possible_paths = loads(string_paths.replace('\'', "\"")) + + for path in possible_paths: + candidate = os.path.join(path, "ansible_collections", "ibm", "operator_collection_sdk") + if os.path.exists(candidate): + collections_root_path = candidate + break + except Exception as e: + error = str(e) + + return collections_root_path, error diff --git a/ibm/operator_collection_sdk/plugins/modules/__init__.py b/ibm/operator_collection_sdk/plugins/modules/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/ibm/operator_collection_sdk/plugins/modules/oc_operatorcollection.py b/ibm/operator_collection_sdk/plugins/modules/oc_operatorcollection.py index 2f12fc4a..ece4c815 100644 --- a/ibm/operator_collection_sdk/plugins/modules/oc_operatorcollection.py +++ b/ibm/operator_collection_sdk/plugins/modules/oc_operatorcollection.py @@ -132,7 +132,7 @@ import os from kubernetes import config, client except ImportError as e: - DEPENDENCY_IMPORT_ERROR = f"Failed to import dependency: {e}" + DEPENDENCY_IMPORT_ERROR = "Failed to import dependency: {}".format(e) def run_operatorcollection_module(): @@ -280,7 +280,7 @@ def extract_and_grep(localpath): return filename, "HII" except Exception as e: - return "", f"Error extracting operator-config yaml: {e}" + return "", "Error extracting operator-config yaml: {}".format(e) def fetch_manager_pod_name_and_copy_collection_to_manager(namespace, localpath, name, version): @@ -309,13 +309,12 @@ def fetch_manager_pod_name_and_copy_collection_to_manager(namespace, localpath, oc_command = "oc cp " + localpath + " " + remote_dir result = subprocess.run(oc_command, shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8') except subprocess.CalledProcessError as e: - return f"Error copying tar file to pod: {e}" + return "Error copying tar file to pod: {}".format(e) - # print(f"Successfully copied {localpath} to {pod_name} at {remote_dir}") return None except Exception as e: - return f"Error fetching manager pod info: {e}" + return "Error fetching manager pod info: {}".format(e) return None diff --git a/ibm/operator_collection_sdk/plugins/modules/oc_suboperatorconfig.py b/ibm/operator_collection_sdk/plugins/modules/oc_suboperatorconfig.py index 97236abe..5a1f9a37 100644 --- a/ibm/operator_collection_sdk/plugins/modules/oc_suboperatorconfig.py +++ b/ibm/operator_collection_sdk/plugins/modules/oc_suboperatorconfig.py @@ -130,7 +130,7 @@ from ansible_collections.kubernetes.core.plugins.module_utils.k8s.runner import run_module from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import CoreException except ImportError as e: - DEPENDENCY_IMPORT_ERROR = f"Failed to import dependency: {e}" + DEPENDENCY_IMPORT_ERROR = "Failed to import dependency: {}".format(e) def run_suboperatorconfig_module(): diff --git a/ibm/operator_collection_sdk/plugins/modules/oc_zoscloudbroker.py b/ibm/operator_collection_sdk/plugins/modules/oc_zoscloudbroker.py new file mode 100644 index 00000000..d718e6bf --- /dev/null +++ b/ibm/operator_collection_sdk/plugins/modules/oc_zoscloudbroker.py @@ -0,0 +1,404 @@ +#!/usr/bin/python + +# (c) Copyright IBM Corp. 2024 +# Apache License, Version 2.0 (see https://opensource.org/licenses/Apache-2.0) +from __future__ import (absolute_import, division, print_function) + +__metaclass__ = type + +DOCUMENTATION = r""" +--- +module: oc_zoscloudbroker + +short_description: This module creates or delete an IBM® z/OS® Cloud Broker (zoscloudbroker) instance. + +version_added: "2.0.0" + +author: + - Yemi Kelani (@yemi-kelani) + +description: This module creates or delete an IBM® z/OS® Cloud Broker (zoscloudbroker) instance. +options: + state: + description: > + Dictates whether an instance of the zoscloudbroker is created or deleted. + When set to C(present), an instance will be created, if it does not already exist. + If set to C(absent), an existing instance will be deleted. + required: false + type: str + default: "present" + choices: ["absent", "present"] + name: + description: The name of the zoscloudbroker. + required: false + type: str + default: "zoscloudbroker" + namespace: + description: The namespace in which to create the instance. + required: true + type: str + accept_license: + description: > + Boolean indicating if the IBM® z/OS® Cloud Broker license agreement (https://ibm.biz/ibm-zoscb-license) + is accepted (a value of true indicates acceptance). + required: false + type: bool + default: false + labels: + description: Labels i.e. type=ibm-zos-cloud-broker. Key-value pairs where key and value are separated by "=". + required: false + default: [] + type: list + elements: str + multi_namespace_suboperators: + description: Boolean indicating whether to expose suboperators across multiple namespaces. + required: false + type: bool + default: true + aliases: ["multi_namespace"] + log_level: + description: Deployment log level. + required: false + type: str + default: "debug" + choices: ["info", "debug", "trace"] + ansible_galaxy_configuration: + description: Configure Ansible Galaxy Server settings. + type: dict + default: {'enabled': 'true', 'url': 'https://galaxy.ansible.com'} + aliases: ["galaxyConfig", "galaxy_config", "galaxy_configuration"] + suboptions: + enabled: + description: Enables Ansible Galaxy integration. Please disable when running in an air-gapped environment. + required: false + type: bool + default: true + url: + description: Specify the URL for Ansible Galaxy. + required: false + type: str + default: "https://galaxy.ansible.com" + storage: + description: > + Persistent Storage is recommended to enable the persistence of imported Ansible Collections. This may be + required in clusters with network firewall configurations. For more information, please refer to + https://ibm.biz/ibm-zoscb-storage. + required: false + type: dict + suboptions: + configure: + description: > + If set to true, create a new Persistent Volume Claim otherwise use existing PVC i.e. + (PVC enabled is True). + required: false + type: bool + volume_access_mode: + description: AccessModes contains the desired access modes the volume should have (ignored if using an existing PVC). + required: false + type: str + default: "ReadWriteMany" + choices: ["ReadWriteMany"] + storage_size: + description: Size represents the storage size (ignored if using an existing PVC). + required: false + type: str + default: "5Gi" + storage_class: + description: Name of the StorageClass required by the claim (ignored if using an existing PVC). + required: false + type: str + volume_mode: + description: VolumeMode defines what type of volume is required by the claim (ignored if using an existing PVC). + required: false + type: str + default: "Filesystem" + choices: ["Filesystem", "filesystem", "FILESYSTEM"] + persistent_volume_claim: + description: Utilize An Existing Persistent Volume Claim (ignored if configuring a new PVC). + required: false + type: str + aliases: ["pvc", "volume_claim"] + +# extends_documentation_fragment: +# - ibm.operator_collection_sdk.documentaion +""" + +EXAMPLES = r""" +- name: Create ZosCloudBroker + ibm.operator_collection_sdk.oc_zoscloudbroker: + state: present + namespace: yemi-test + accept_license: true + multi_namespace: true + log_level: trace + storage: + configure: true + storage_class: rook-cephfs + register: zcb_results + +- name: Create ZosCloudBroker + ibm.operator_collection_sdk.oc_zoscloudbroker: + state: present + name: zoscloudbroker + namespace: yemi-test + accept_license: true + multi_namespace: true + log_level: debug + labels: + - test=true + - namespace=yemi-test + storage: + enabled: true + pvc: zoscloudbroker + +- name: Create ZosCloudBroker + ibm.operator_collection_sdk.oc_zoscloudbroker: + state: present + namespace: yemi-test-2 + accept_license: true + storage: + enabled: true + pvc: zoscloudbroker + register: zcb_results + +- name: Delete ZosCloudBroker + ibm.operator_collection_sdk.oc_zoscloudbroker: + state: absent + name: zoscloudbroker + namespace: yemi-test-2 + register: zcb_results +""" + +RETURN = r""" +changed: + description: Boolean indicating whether target was modified. + returned: always + type: bool +error: + description: Boolean indicating whether the module errored. + returned: always + type: bool +result: + description: The Custom Resource Definition returned by the performed operation. + returned: success + type: complex + contains: + api_version: + description: Version schema. + returned: success + type: str + sample: v1 + kind: + description: The resource type this object is. + returned: success + type: str + sample: Status + status: + description: The status of the request. + returned: success + type: str + sample: Success + metadata: + description: Target resource metadata. + returned: success + type: complex + details: + description: Information about the target resource. + returned: success + type: complex + contains: + group: + description: API group. + returned: success + type: str + sample: zoscb.ibm.com + kind: + description: Custom resource kind. + returned: success + type: str + sample: zoscloudbrokers + name: + description: Custom resource name. + returned: success + type: str + sample: zoscloudbroker + uid: + description: Resource UID. + returned: success + type: str + sample: 1f922d43-ce6f-42fd-9290-75f2a274a6d2 +""" + +from ansible.module_utils.basic import AnsibleModule + +DEPENDENCY_IMPORT_ERROR = None + +try: + import os + import re + import copy + from jinja2 import Environment, FileSystemLoader + from ..module_utils.util import get_collection_root_path + from ansible_collections.kubernetes.core.plugins.module_utils.k8s.core import AnsibleK8SModule + from ansible_collections.kubernetes.core.plugins.module_utils.k8s.runner import run_module + from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import CoreException +except ImportError as e: + DEPENDENCY_IMPORT_ERROR = "Failed to import dependency: {}".format(e) + + +def validate_module_parameters(module, result): + # make a copy of module params + params_copy = copy.deepcopy(module.params) + + if params_copy["state"] == "absent": + return params_copy + + # set default values if necessary + if "configure" not in params_copy["storage"]: + params_copy["storage"]["configure"] = False + if "enabled" not in params_copy["storage"]: + params_copy["storage"]["enabled"] = False + + # validate storage has either configured or enabled or both are false + if params_copy["storage"]["configure"] and params_copy["storage"]["enabled"]: + module.fail_json( + msg="Invalid parameters; Storage parameters 'configure' and 'enabled' cannot both be true.", + **result) + + # validate required params are present + if params_copy["storage"]["configure"]: + required_params = [ + # "volume_access_mode" + # "volume_mode", + # "storage_size", + "storage_class" + ] + for param in required_params: + if param not in params_copy["storage"] \ + or params_copy["storage"][param] == "" \ + or params_copy["storage"][param] is None: + module.fail_json( + msg="Missing required argument '{}'. The following arguments must be suppled when \ + argument storage.configure is True: {}.".format(param, ', '.join(required_params)), + **result) + elif params_copy["storage"]["enabled"]: + if "persistent_volume_claim" not in params_copy["storage"] \ + or params_copy["storage"]["persistent_volume_claim"] == "" \ + or params_copy["storage"]["persistent_volume_claim"] is None: + module.fail_json( + msg="Missing required argument 'persistent_volume_claim'. persistent_volume_claim must be \ + suppled when argument storage.enabled is True.", + **result) + + # validate label format if they exist + if "labels" in params_copy: + labels = {} + for label in params_copy["labels"]: + if re.match("^[^=]*=[^=]*$", label) is None: + module.fail_json( + msg="Recieved label with misshapen form: '{}'. Each label in the list should take the \ + form 'key=value'.".format(label), + **result) + else: + [key, value] = label.split("=") + labels[key] = value + + params_copy["labels"] = labels + + return params_copy + + +def create_and_validate_module(): + module_args = dict( + state=dict(type="str", required=False, default="present", choices=["absent", "present"]), + name=dict(type="str", required=False, default="zoscloudbroker"), + namespace=dict(type="str", required=True), + accept_license=dict(type="bool", required=False, default=False), + labels=dict(type="list", elements="str", required=False, default=[]), + multi_namespace_suboperators=dict(type="bool", required=False, default=True, aliases=["multi_namespace"]), + log_level=dict(type="str", required=False, default="debug", choices=["info", "debug", "trace"]), + ansible_galaxy_configuration=dict( + type="dict", + required=False, + default=dict(enabled="true", url="https://galaxy.ansible.com"), + aliases=["galaxy_configuration", "galaxyConfig", "galaxy_config"], + options=dict( + enabled=dict(type="bool", required=False, default=True), + url=dict(type="str", required=False, default="https://galaxy.ansible.com"), + ) + ), + storage=dict( + type="dict", + required=False, + options=dict( + configure=dict(type="bool", required=False), + enabled=dict(type="bool", required=False), + volume_access_mode=dict(type="str", default="ReadWriteMany", choices=["ReadWriteMany"]), + storage_size=dict(type="str", required=False, default="5Gi"), + storage_class=dict(type="str", required=False), + volume_mode=dict(type="str", required=False, default="Filesystem", choices=["Filesystem", "filesystem", "FILESYSTEM"]), + persistent_volume_claim=dict(type="str", required=False, aliases=["pvc", "volume_claim"]) + ) + ) + ) + + if DEPENDENCY_IMPORT_ERROR is not None: + module = AnsibleModule(argument_spec=module_args) + module.fail_json(msg=DEPENDENCY_IMPORT_ERROR) + + module = AnsibleK8SModule( + module_class=AnsibleModule, + argument_spec=module_args, + supports_check_mode=True, + required_if=[ + ["state", "present", ["accept_license", "storage"], True], + ["state", "absent", ["name"], True] + ] + ) + + result = dict( + changed=False, # if this module effectively modified the target + error=False + ) + + validated_params = validate_module_parameters(module=module, result=result) + + return module, result, validated_params + + +def run_zoscloudbroker_module(module, result, validated_params): + # if in only check mode, return the state with no modifications + if module.check_mode: + module.exit_json(**result) + + # load template and render CRD + collections_root_path, error = get_collection_root_path() + if error is not None: + module.fail_json(msg="Failed to locate the ibm.operator_collection_sdk collection in paths \ + specified under COLLECTIONS_PATHS in the ansible.cfg: {}".format(error)) + + template_path = os.path.join(collections_root_path, "playbooks", "templates") + environment = Environment(loader=FileSystemLoader(searchpath=template_path)) + template = environment.get_template("zoscloudbroker.yml.j2") + custom_resource_definition = template.render(validated_params) + module.params["resource_definition"] = custom_resource_definition + + # attempt to modify target + try: + run_module(module) + result["changed"] = True + except CoreException as e: + result["error"] = True + module.fail_from_exception(e) + + # successful module execution, exit and pass results + module.exit_json(**result) + + +def main(): + module, result, validated_params = create_and_validate_module() + run_zoscloudbroker_module(module, result, validated_params) + + +if __name__ == '__main__': + main() diff --git a/ibm/operator_collection_sdk/plugins/modules/oc_zosendpoint.py b/ibm/operator_collection_sdk/plugins/modules/oc_zosendpoint.py index 4e25ecb8..1a47e4e1 100644 --- a/ibm/operator_collection_sdk/plugins/modules/oc_zosendpoint.py +++ b/ibm/operator_collection_sdk/plugins/modules/oc_zosendpoint.py @@ -124,7 +124,7 @@ from ansible_collections.kubernetes.core.plugins.module_utils.k8s.runner import run_module from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import CoreException except ImportError as e: - DEPENDENCY_IMPORT_ERROR = f"Failed to import dependency: {e}" + DEPENDENCY_IMPORT_ERROR = "Failed to import dependency: {}".format(e) def run_zosendpoint_module(): diff --git a/ibm/operator_collection_sdk/roles/upload_collection_to_manager/tasks/main.yml b/ibm/operator_collection_sdk/roles/upload_collection_to_manager/tasks/main.yml index 97471420..68ede150 100644 --- a/ibm/operator_collection_sdk/roles/upload_collection_to_manager/tasks/main.yml +++ b/ibm/operator_collection_sdk/roles/upload_collection_to_manager/tasks/main.yml @@ -69,3 +69,66 @@ - name: Copy local build to manager pod using new collection path ansible.builtin.command: oc cp {{ find_result.files[0].path }} "{{ pod_results.resources[0].metadata.namespace }}/{{ pod_results.resources[0].metadata.name }}":/opt/collections/suboperator/{{ operator_name }}/{{ operator_version }}/{{ find_result.files[0].path | basename }} when: soc_results.resources | length == 0 or (redeploy is defined and redeploy is true) +# +# Copyright 2023 IBM Inc. All rights reserved +# SPDX-License-Identifier: Apache2.0 +# + +--- +- name: Get Manager Pod Name + kubernetes.core.k8s_info: + kind: Pod + namespace: "{{ namespace }}" + label_selectors: + - component = manager + register: pod_results + +- name: Validate manager pod exists + ansible.builtin.fail: + msg: "Manager pod doesn't exist or multiple manager pods listed in namespace" + when: pod_results.resources | length == 0 or pod_results.resources | length > 1 + +- name: Get collection filepath + ansible.builtin.find: + paths: "{{ path }}/local/builds/{{ operator_version }}" + register: find_result + +- name: Get SubOperatorConfig + kubernetes.core.k8s_info: + api_version: zoscb.ibm.com/v2beta2 + kind: SubOperatorConfig + namespace: "{{ namespace }}" + label_selectors: + - "operator-name = {{ operator_name }}" + register: soc_results + +- name: Validate SubOperatorConfig exists + ansible.builtin.debug: + msg: "SubOperatorConfig doesn't exist or multiple SubOperatorConfigs listed in namespace" + when: soc_results.resources | length == 0 or soc_results.resources | length > 1 + +- name: Get collection file path in manager Pod + kubernetes.core.k8s_info: + api_version: zoscb.ibm.com/v2beta2 + kind: OperatorCollection + name: "{{ soc_results.resources[0].spec.operatorCollection }}" + namespace: "{{ namespace }}" + register: oc_results + when: soc_results.resources | length > 0 + +- name: Validate OperatorCollection exists + ansible.builtin.fail: + msg: "OperatorCollection doesn't exist" + when: soc_results.resources | length > 0 and oc_results.resources | length == 0 + +- name: Copy local build to manager pod using existing collection path + ansible.builtin.command: oc cp {{ find_result.files[0].path }} "{{ pod_results.resources[0].metadata.namespace }}/{{ pod_results.resources[0].metadata.name }}":"{{ oc_results.resources[0].status.config.collectionPath }}" + when: soc_results.resources | length > 0 and oc_results.resources | length > 0 and (redeploy is not defined or redeploy is false) + +- name: Create directory on pod if doesn't exist + ansible.builtin.command: oc exec -i -n "{{ pod_results.resources[0].metadata.namespace }}" "{{ pod_results.resources[0].metadata.name }}" -- mkdir -p /opt/collections/suboperator/{{ operator_name }}/{{ operator_version }} + when: soc_results.resources | length == 0 and (redeploy is not defined or redeploy is false) + +- name: Copy local build to manager pod using new collection path + ansible.builtin.command: oc cp {{ find_result.files[0].path }} "{{ pod_results.resources[0].metadata.namespace }}/{{ pod_results.resources[0].metadata.name }}":/opt/collections/suboperator/{{ operator_name }}/{{ operator_version }}/{{ find_result.files[0].path | basename }} + when: soc_results.resources | length == 0 or (redeploy is defined and redeploy is true) diff --git a/ibm/operator_collection_sdk/tests/README.md b/ibm/operator_collection_sdk/tests/README.md new file mode 100644 index 00000000..669395cd --- /dev/null +++ b/ibm/operator_collection_sdk/tests/README.md @@ -0,0 +1,43 @@ +### Running Tests Locally +--- + +> This document does not cover molecule testing. + +Test scripts can be run from anywhere within the collection, given the current working directory is `~/**/ibm/operator_collection_sdk/*`. + +By default, the tests will install the codebase/collection locally. This functionality can be configured with the following flags:`-i` / `--install-collection` +which can be set either `true` or `false`, i.e. `--install-collection=false`. + +Usage: +- `--install-collection=`, default: `true` +- Alias: `-i=` + +**Quick Start:** +1. Navigate to `~/**/ibm/operator_collection_sdk/*`. +2. Deactivate your virtual environment (if it is active). +3. Run a test script. +--- + +#### Unit Tests +To install the collection and run all unit tests: +```bash +chmod +x ./tests/unit/unit.sh +./tests/unit/unit.sh +``` +--- + +#### Sanity Tests +To install the collection and run sanity tests: +```bash +chmod +x ./tests/unit/unit.sh +./tests/unit/unit.sh +``` +--- + +#### Integration Tests +To install the collection and run all Integration tests: +```bash +chmod +x ./tests/integration/integration.sh +./tests/integration/integration.sh +``` +Note: This test will set up and teardown a cluster environment too. \ No newline at end of file diff --git a/ibm/operator_collection_sdk/tests/integration/integration.sh b/ibm/operator_collection_sdk/tests/integration/integration.sh new file mode 100755 index 00000000..5dcd71d2 --- /dev/null +++ b/ibm/operator_collection_sdk/tests/integration/integration.sh @@ -0,0 +1,107 @@ +#!/usr/bin/env bash + +# (c) Copyright IBM Corp. 2024 +# Apache License, Version 2.0 (see https://opensource.org/licenses/Apache-2.0) + +function parseCommandLine { + for arg in "$@"; do + case $arg in + -i=*|--install-collection=*) + install_collection=${arg#*=} + break + ;; + -i|--install-collection) + install_collection=true + break + ;; + *) + echo "Unrecognized option: $arg" + echo "Usage: [--install-collection=] (alias: [-i=]), default: true" + exit 1; + ;; + esac + done + + if [[ $(echo "${install_collection}" | tr '[:upper:]' '[:lower:]') == "true" ]]; then + install_collection=true + else + install_collection=false + fi +} + + +install_collection=true +parseCommandLine "$@" + + +# get collection root path +cwd=$(pwd) +collection_path="" +if [[ ${cwd} =~ "ibm/operator_collection_sdk" ]]; then + collection_path=$(echo "${cwd}" | sed -e "s/ibm\/operator_collection_sdk.*$/ibm\/operator_collection_sdk/") +else + echo -e "\n\033[1;31m Expected script to be run from somewhere within '~/**/ibm/operator_collection_sdk/*' instead got '${cwd}'\033[00m" + exit 1 +fi + +# Install collection locally if flag is set +if [[ "${install_collection}" == "true" ]]; then + printf "\n\033[1;32m Installing collection locally... \033[00m" + ansible-galaxy collection install "${collection_path}" -f + cd "$cwd" +fi + + +# Populate integration_config.yml file with environment variables +ocpnamespace="" +truncate -s 0 "$collection_path"/tests/integration/integration_config.yml +while read -r line; +do + if [[ "$line" =~ "#" ]]; then + continue + fi + eval 'echo "'"$line"'" >> "'"$collection_path"'"/tests/integration/integration_config.yml' + + # determine ocpnamespace + if [[ "$line" =~ "ocp_namespace" ]]; then + l=$(eval 'echo "'"$line"'"') + + # isolate namespace | trim spaces | make lowercase | replace non-alphanumeric with "-" + ocpnamespace=$(echo "$l" | sed -e 's/^.*:[[:space:]]*//' | sed 's/[[:space:]]*$//g' | tr '[:upper:]' '[:lower:]' | sed -e 's/[^-a-zA-Z0-9]/-/g') + echo 'ocpnamespace: "'"$ocpnamespace"'"' >> "$collection_path"/tests/integration/integration_config.yml + fi +done < "$collection_path/tests/integration/integration_config.yml.template" + + +printf "Setting Up Cluster for Integration Tests...\n" +ANSIBLE_JINJA2_NATIVE=true ansible-playbook "$collection_path"/playbooks/molecule/cluster_setup.yml \ + --extra-vars @"$collection_path"/tests/integration/integration_config.yml + + +# Run Integration Tests +cwd=$(pwd) +exit_status=0 +cd ~/.ansible/collections/ansible_collections/ibm/operator_collection_sdk +ansible-test integration -v --venv +exit_status="$?" +cd "$cwd" + +if [[ ${exit_status} != 0 ]] \ +&& [[ $(echo "$VIRTUAL_ENV" | awk '{print length}') != 0 ]] \ +|| [[ -n "$VIRTUAL_ENV" ]]; then + echo -e "\n\033[1;31m Hint: Is your virtual environment still on? If so, try turning it off (deactivate). \033[00m" + echo -e '\033[1;31m "'"$VIRTUAL_ENV"'" \033[00m\n' + exit "$exit_status" +fi + + +echo "Tearing Down Cluster Environment after Integration Tests..." +ANSIBLE_JINJA2_NATIVE=true ansible-playbook "$collection_path"/playbooks/molecule/cluster_clean.yml \ + --extra-vars @"$collection_path"/tests/integration/integration_config.yml + +_exit_status="$?" +if [[ ${_exit_status} != 0 ]]; then + echo -e "\n\033[1;31m Failed to tear down cluster environment after Integration Tests! Review logs. \033[00m" +fi + +exit "$exit_status" \ No newline at end of file diff --git a/ibm/operator_collection_sdk/tests/integration/integration_clean.sh b/ibm/operator_collection_sdk/tests/integration/integration_clean.sh new file mode 100755 index 00000000..2d99139e --- /dev/null +++ b/ibm/operator_collection_sdk/tests/integration/integration_clean.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash + +# (c) Copyright IBM Corp. 2024 +# Apache License, Version 2.0 (see https://opensource.org/licenses/Apache-2.0) + +# get collection root path +function parseCommandLine { + for arg in "$@"; do + case $arg in + --collection-root=*) + collection_root=${arg#*=} + break + ;; + *) + echo "Unrecognized option: $arg" + echo "Usage: [--collection-root=], default: ''" + exit 1; + ;; + esac + done + + if [[ "$collection_root" == "" ]]; then + echo -e "\n\033[1;31m Error: Must supply path to --collection-root, i.e. '--collection-root=~/**/ibm/operator_collection_sdk' \033[00m" + exit 1 + fi +} + +parseCommandLine "$@" + +# Populate integration_config.yml file with environment variables +ocpnamespace="" +truncate -s 0 "$collection_root"/tests/integration/integration_config.yml +while read -r line; +do + if [[ "$line" =~ "#" ]]; then + continue + fi + eval 'echo "'"$line"'" >> "'"$collection_root"'"/tests/integration/integration_config.yml' + + # determine ocpnamespace + if [[ "$line" =~ "ocp_namespace" ]]; then + l=$(eval 'echo "'"$line"'"') + + # isolate namespace | trim spaces | make lowercase | replace non-alphanumeric with "-" + ocpnamespace=$(echo "$l" | sed -e 's/^.*:[[:space:]]*//' | sed 's/[[:space:]]*$//g' | tr '[:upper:]' '[:lower:]' | sed -e 's/[^-a-zA-Z0-9]/-/g') + echo 'ocpnamespace: "'"$ocpnamespace"'"' >> "$collection_root"/tests/integration/integration_config.yml + fi +done < "$collection_root/tests/integration/integration_config.yml.template" + + +echo "Tearing Down Cluster Environment after Integration Tests..." +ANSIBLE_JINJA2_NATIVE=true ansible-playbook "$collection_root"/playbooks/molecule/cluster_clean.yml \ + --extra-vars @"$collection_root"/tests/integration/integration_config.yml + +exit_status="$?" +if [[ ${exit_status} != 0 ]]; then + echo -e "\n\033[1;31m Failed to tear down cluster environment after Integration Tests! Review logs. \033[00m" +fi + +exit "$exit_status" \ No newline at end of file diff --git a/ibm/operator_collection_sdk/tests/integration/integration_config.yml.template b/ibm/operator_collection_sdk/tests/integration/integration_config.yml.template new file mode 100644 index 00000000..59c38216 --- /dev/null +++ b/ibm/operator_collection_sdk/tests/integration/integration_config.yml.template @@ -0,0 +1,11 @@ +# +# Copyright 2024 IBM Inc. All rights reserved +# SPDX-License-Identifier: Apache2.0 +# +# Leave a trailing newline at the end of this file. +# Do not add secrets/tokens to this file. +--- +ocp_namespace: ${OCP_NAMESPACE:-ocsdk-integration} +zoscb_release: ${ZOSCB_RELEASE:-ibm-zoscb.v2.2.5} +zoscloudbroker_name: zoscloudbroker +subscription_name: ibm-zoscb diff --git a/ibm/operator_collection_sdk/tests/integration/integration_setup.sh b/ibm/operator_collection_sdk/tests/integration/integration_setup.sh new file mode 100755 index 00000000..21c396c9 --- /dev/null +++ b/ibm/operator_collection_sdk/tests/integration/integration_setup.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash + +# (c) Copyright IBM Corp. 2024 +# Apache License, Version 2.0 (see https://opensource.org/licenses/Apache-2.0) + +# get collection root path +function parseCommandLine { + for arg in "$@"; do + case $arg in + --collection-root=*) + collection_root=${arg#*=} + break + ;; + *) + echo "Unrecognized option: $arg" + echo "Usage: [--collection-root=], default: ''" + exit 1; + ;; + esac + done + + if [[ "$collection_root" == "" ]]; then + echo -e "\n\033[1;31m Error: Must supply path to --collection-root, i.e. '--collection-root=~/**/ibm/operator_collection_sdk' \033[00m" + exit 1 + fi +} + +parseCommandLine "$@" + +# Populate integration_config.yml file with environment variables +ocpnamespace="" +truncate -s 0 "$collection_root"/tests/integration/integration_config.yml +while read -r line; +do + if [[ "$line" =~ "#" ]]; then + continue + fi + eval 'echo "'"$line"'" >> "'"$collection_root"'"/tests/integration/integration_config.yml' + + # determine ocpnamespace + if [[ "$line" =~ "ocp_namespace" ]]; then + l=$(eval 'echo "'"$line"'"') + + # isolate namespace | trim spaces | make lowercase | replace non-alphanumeric with "-" + ocpnamespace=$(echo "$l" | sed -e 's/^.*:[[:space:]]*//' | sed 's/[[:space:]]*$//g' | tr '[:upper:]' '[:lower:]' | sed -e 's/[^-a-zA-Z0-9]/-/g') + echo 'ocpnamespace: "'"$ocpnamespace"'"' >> "$collection_root"/tests/integration/integration_config.yml + fi +done < "$collection_root/tests/integration/integration_config.yml.template" + + +printf "Setting Up Cluster for Integration Tests...\n" +ANSIBLE_JINJA2_NATIVE=true ansible-playbook "$collection_root"/playbooks/molecule/cluster_setup.yml \ + --extra-vars @"$collection_root"/tests/integration/integration_config.yml + +exit "$?" \ No newline at end of file diff --git a/ibm/operator_collection_sdk/tests/integration/requirements.txt b/ibm/operator_collection_sdk/tests/integration/requirements.txt new file mode 100644 index 00000000..4b1a0d62 --- /dev/null +++ b/ibm/operator_collection_sdk/tests/integration/requirements.txt @@ -0,0 +1,2 @@ +kubernetes +pyaml \ No newline at end of file diff --git a/ibm/operator_collection_sdk/tests/integration/requirements.yml b/ibm/operator_collection_sdk/tests/integration/requirements.yml new file mode 100644 index 00000000..e1ae55f6 --- /dev/null +++ b/ibm/operator_collection_sdk/tests/integration/requirements.yml @@ -0,0 +1,2 @@ +collections: + - kubernetes.core diff --git a/ibm/operator_collection_sdk/tests/integration/targets/oc_zoscloudbroker/playbook.yml b/ibm/operator_collection_sdk/tests/integration/targets/oc_zoscloudbroker/playbook.yml new file mode 100644 index 00000000..b2f4eb93 --- /dev/null +++ b/ibm/operator_collection_sdk/tests/integration/targets/oc_zoscloudbroker/playbook.yml @@ -0,0 +1,13 @@ +# +# Copyright 2024 IBM Inc. All rights reserved +# SPDX-License-Identifier: Apache2.0 +# + +--- +- hosts: localhost + gather_facts: false + vars_files: + - ../../integration_config.yml + roles: + - role: ../oc_zoscloudbroker + \ No newline at end of file diff --git a/ibm/operator_collection_sdk/tests/integration/targets/oc_zoscloudbroker/runme.sh b/ibm/operator_collection_sdk/tests/integration/targets/oc_zoscloudbroker/runme.sh new file mode 100755 index 00000000..06623c43 --- /dev/null +++ b/ibm/operator_collection_sdk/tests/integration/targets/oc_zoscloudbroker/runme.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +set -eux +ansible-playbook playbook.yml "$@" \ No newline at end of file diff --git a/ibm/operator_collection_sdk/tests/integration/targets/oc_zoscloudbroker/tasks/main.yml b/ibm/operator_collection_sdk/tests/integration/targets/oc_zoscloudbroker/tasks/main.yml new file mode 100644 index 00000000..9e4778d2 --- /dev/null +++ b/ibm/operator_collection_sdk/tests/integration/targets/oc_zoscloudbroker/tasks/main.yml @@ -0,0 +1,94 @@ +# +# Copyright 2024 IBM Inc. All rights reserved +# SPDX-License-Identifier: Apache2.0 +# + +--- +- name: Test oc_zoscloudbroker module + block: + - name: Delete ZosCloudBroker if it exists + kubernetes.core.k8s: + state: absent + api_version: zoscb.ibm.com/v2beta1 + kind: ZosCloudBroker + name: "{{ zoscloudbroker_name }}" + namespace: "{{ ocpnamespace }}" + wait: true + wait_sleep: 5 + wait_timeout: 140 + ignore_errors: true + + - name: Create ZosCloudBroker + ibm.operator_collection_sdk.oc_zoscloudbroker: + state: present + name: "{{ zoscloudbroker_name }}" + namespace: "{{ ocpnamespace }}" + accept_license: true + multi_namespace: true + log_level: trace + labels: + - mylabel=testlabel + galaxy_configuration: + enabled: false + url: "www.example.com" + storage: + enabled: false + configure: false + + - name: Validating ZosCloudBroker installed successfully + kubernetes.core.k8s_info: + api_version: zoscb.ibm.com/v2beta1 + kind: ZosCloudBroker + name: "{{ zoscloudbroker_name }}" + namespace: "{{ ocpnamespace }}" + register: zoscb_results + until: "zoscb_results.resources[0].status.phase == 'Successful'" + retries: 30 + delay: 5 + + - name: Assert ZosCloudBroker fields are accurate + ansible.builtin.assert: + that: + - zoscb_results.resources[0].spec.galaxyConfig.enabled == false + - zoscb_results.resources[0].spec.galaxyConfig.galaxyURL == 'www.example.com' + - zoscb_results.resources[0].metadata.labels.mylabel == 'testlabel' + - zoscb_results.resources[0].spec.logLevel == 'trace' + - zoscb_results.resources[0].spec.storage.enabled == false + - zoscb_results.resources[0].spec.storage.configure == false + + - name: Delete ZosCloudBroker + ibm.operator_collection_sdk.oc_zoscloudbroker: + state: absent + name: "{{ zoscloudbroker_name }}" + namespace: "{{ ocpnamespace }}" + register: zcb_results + + - name: Validate ZosCloudBroker is deleted + kubernetes.core.k8s_info: + api_version: zoscb.ibm.com/v2beta1 + kind: ZosCloudBroker + name: "{{ zoscloudbroker_name }}" + namespace: "{{ ocpnamespace }}" + register: zoscb_results + + - name: Assert ZosCloudBroker is deleted + ansible.builtin.assert: + that: + - zoscb_results.resources | length == 0 + + always: + - name: Delete ZosCloudBoker + kubernetes.core.k8s: + state: absent + api_version: zoscb.ibm.com/v2beta1 + kind: ZosCloudBroker + name: "{{ zoscloudbroker_name }}" + namespace: "{{ ocpnamespace }}" + wait: true + wait_sleep: 5 + wait_timeout: 140 + ignore_errors: true + when: zoscloudbroker_name is defined + + - name: Revert Changes to Cluster Environment + include_tasks: revert_changes.yml diff --git a/ibm/operator_collection_sdk/tests/integration/targets/oc_zoscloudbroker/tasks/revert_changes.yml b/ibm/operator_collection_sdk/tests/integration/targets/oc_zoscloudbroker/tasks/revert_changes.yml new file mode 100644 index 00000000..0aa10f09 --- /dev/null +++ b/ibm/operator_collection_sdk/tests/integration/targets/oc_zoscloudbroker/tasks/revert_changes.yml @@ -0,0 +1,28 @@ +# +# Copyright 2024 IBM Inc. All rights reserved +# SPDX-License-Identifier: Apache2.0 +# + +--- +- block: + - name: Create ZosCloudBoker + kubernetes.core.k8s: + state: present + definition: + apiVersion: zoscb.ibm.com/v2beta1 + kind: ZosCloudBroker + metadata: + name: "{{ zoscloudbroker_name }}" + namespace: "{{ ocpnamespace }}" + spec: + catalogResources: {} + license: + accept: true + logLevel: trace + managerResources: {} + storage: + configure: false + enabled: false + size: 5Gi + volumeMode: Filesystem + uiResources: {} \ No newline at end of file diff --git a/ibm/operator_collection_sdk/tests/sanity/ignore-2.16.txt b/ibm/operator_collection_sdk/tests/sanity/ignore-2.16.txt index 838cbdbb..8deead41 100644 --- a/ibm/operator_collection_sdk/tests/sanity/ignore-2.16.txt +++ b/ibm/operator_collection_sdk/tests/sanity/ignore-2.16.txt @@ -1,3 +1,10 @@ +<<<<<<< HEAD +======= +plugins/modules/oc_zoscloudbroker.py validate-modules:parameter-type-not-in-doc # "enabled" var is erroneously flagged +plugins/modules/oc_zoscloudbroker.py validate-modules:undocumented-parameter # "enabled" var is erroneously flagged +plugins/modules/oc_zoscloudbroker.py validate-modules:return-syntax-error # "metadata" return field varies wildly, can't document +plugins/modules/oc_zoscloudbroker.py validate-modules:missing-gplv3-license # ignore gplv3 license, we use apache +>>>>>>> v2-cloudbroker playbooks/templates/endpoint.yml yamllint!skip playbooks/templates/suboperatorconfig.yml yamllint!skip playbooks/templates/operatorcollection.yml yamllint!skip \ No newline at end of file diff --git a/ibm/operator_collection_sdk/tests/sanity/ignore-2.9.txt b/ibm/operator_collection_sdk/tests/sanity/ignore-2.9.txt new file mode 100644 index 00000000..dd850b5c --- /dev/null +++ b/ibm/operator_collection_sdk/tests/sanity/ignore-2.9.txt @@ -0,0 +1,4 @@ +plugins/modules/oc_zoscloudbroker.py validate-modules:parameter-type-not-in-doc # "enabled" var is erroneously flagged +plugins/modules/oc_zoscloudbroker.py validate-modules:undocumented-parameter # "enabled" var is erroneously flagged +plugins/modules/oc_zoscloudbroker.py validate-modules:return-syntax-error # "metadata" return field varies wildly, can't document +plugins/modules/oc_zoscloudbroker.py validate-modules:missing-gplv3-license # ignore gplv3 license, we use apache \ No newline at end of file diff --git a/ibm/operator_collection_sdk/tests/sanity/sanity.sh b/ibm/operator_collection_sdk/tests/sanity/sanity.sh new file mode 100755 index 00000000..0471f756 --- /dev/null +++ b/ibm/operator_collection_sdk/tests/sanity/sanity.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash + +# (c) Copyright IBM Corp. 2024 +# Apache License, Version 2.0 (see https://opensource.org/licenses/Apache-2.0) + +function parseCommandLine { + for arg in "$@"; do + case $arg in + -i=*|--install-collection=*) + install_collection=${arg#*=} + break + ;; + -i|--install-collection) + install_collection=true + break + ;; + *) + echo "Unrecognized option: $arg" + echo "Usage: [--install-collection=] (alias: [-i=]), default: true" + exit 1; + ;; + esac + done + + if [[ $(echo "${install_collection}" | tr '[:upper:]' '[:lower:]') == "true" ]]; then + install_collection=true + else + install_collection=false + fi +} + +install_collection=true +parseCommandLine "$@" + +if [[ "${install_collection}" == "true" ]]; then + cwd=$(pwd) + if [[ ${cwd} =~ "ibm/operator_collection_sdk" ]]; then + printf "\n\033[1;32m Installing collection locally... \033[00m" + collection_path=$(echo "${cwd}" | sed -e "s/ibm\/operator_collection_sdk.*$/ibm\/operator_collection_sdk/g") + ansible-galaxy collection install "${collection_path}" -f + else + echo -e "\n\033[1;31m Expected script to be run from somewhere within '~/**/ibm/operator_collection_sdk/*' instead got '${cwd}'\033[00m" + exit 1 + fi +fi + +# Run Sanity Tests +cd ~/.ansible/collections/ansible_collections/ibm/operator_collection_sdk +ansible-test sanity -v --venv +exit_status="$?" + +if [[ ${exit_status} != 0 ]] \ +&& [[ $(echo "$VIRTUAL_ENV" | awk '{print length}') != 0 ]] \ +|| [[ -n "$VIRTUAL_ENV" ]]; then + echo -e "\n\033[1;31m Hint: Is your virtual environment still on? If so, try turning it off (deactivate). \033[00m" + echo -e '\033[1;31m "'"$VIRTUAL_ENV"'" \033[00m\n' + exit "$exit_status" +fi + +exit "$exit_status" \ No newline at end of file diff --git a/ibm/operator_collection_sdk/tests/unit/__init__.py b/ibm/operator_collection_sdk/tests/unit/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/ibm/operator_collection_sdk/tests/unit/modules/__init__.py b/ibm/operator_collection_sdk/tests/unit/modules/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/ibm/operator_collection_sdk/tests/unit/modules/test_oc_zoscloudbroker.py b/ibm/operator_collection_sdk/tests/unit/modules/test_oc_zoscloudbroker.py new file mode 100644 index 00000000..3e5adcd1 --- /dev/null +++ b/ibm/operator_collection_sdk/tests/unit/modules/test_oc_zoscloudbroker.py @@ -0,0 +1,152 @@ +# (c) Copyright IBM Corp. 2024 +# Apache License, Version 2.0 (see https://opensource.org/licenses/Apache-2.0) +from __future__ import (absolute_import, division, print_function) + +__metaclass__ = type + +import unittest +from unittest.mock import patch +from ansible.module_utils.basic import AnsibleModule + +from plugins.modules import oc_zoscloudbroker +from tests.unit.utils.mock import ( + error_equal, + fail_json, + exit_json, + AnsibleFailJson, + AnsibleExitJson, + set_module_args, + get_bin_path +) + + +class TestValidateParams(unittest.TestCase): + mock_module_params = dict( + state="present", # present, absent + name="zoscloudbroker", + namespace="fake-namespace", + accept_license=True, + labels=[], + multi_namespace_suboperators=True, + log_level="debug", # info, debug, trace + ansible_galaxy_configuration=dict( + enabled="true", + url="https://galaxy.ansible.com" + ), + storage=dict( + configure=False, + enabled=False, + volume_access_mode="ReadWriteMany", + storage_size="5Gi", + storage_class="fake-storage-class", + volume_mode="Filesystem", + persistent_volume_claim="zoscloudbroker" + ) + ) + + def setUp(self): + self.mock_module_helper = patch.multiple( + AnsibleModule, + exit_json=exit_json, + fail_json=fail_json, + get_bin_path=get_bin_path + ) + + self.mock_module_helper.start() + self.addCleanup(self.mock_module_helper.stop) + + def test_module_fails_when_no_args_passed(self): + with self.assertRaises(AnsibleFailJson): + set_module_args({}) + oc_zoscloudbroker.create_and_validate_module() + + def test_module_fails_when_storage_enabled_and_configure_true(self): + with self.assertRaises(AnsibleFailJson) as result: + args = {**self.mock_module_params} + args["storage"]["enabled"] = True + args["storage"]["configure"] = True + set_module_args(args) + oc_zoscloudbroker.create_and_validate_module() + + assert ( + result.exception.args[0]["msg"] + == "Invalid parameters; Storage parameters 'configure' and 'enabled' cannot both be true." + ) + + def test_module_fails_when_storage_enabled_and_pcv_missing(self): + with self.assertRaises(AnsibleFailJson) as result: + args = {**self.mock_module_params} + args["storage"] = {"enabled": True} + set_module_args(args) + oc_zoscloudbroker.create_and_validate_module() + + assert ( + error_equal( + result.exception.args[0]["msg"], + "Missing required argument 'persistent_volume_claim'. persistent_volume_claim must be \ + suppled when argument storage.enabled is True.")) + + def test_module_created_when_storage_enabled_pcv_present(self): + with self.assertRaises(AnsibleExitJson): + args = {**self.mock_module_params} + args["storage"]["enabled"] = True + set_module_args(args, check_mode=True) + oc_zoscloudbroker.main() + + def test_module_fails_when_storage_configured_required_args_missing(self): + with self.assertRaises(AnsibleFailJson) as result: + args = {**self.mock_module_params} + args["storage"] = {"configure": True} + set_module_args(args) + oc_zoscloudbroker.create_and_validate_module() + + assert ( + error_equal( + result.exception.args[0]["msg"], + "Missing required argument 'storage_class'. The following arguments must be suppled when \ + argument storage.configure is True: storage_class.")) + + def test_module_created_when_storage_configured_required_args_present(self): + with self.assertRaises(AnsibleExitJson): + args = {**self.mock_module_params} + args["storage"]["configure"] = True + set_module_args(args, check_mode=True) + oc_zoscloudbroker.main() + + def test_module_validates_and_constructs_valid_labels_arg(self): + args = {**self.mock_module_params} + args["labels"] = ["TestLabel1=LabelValue1", "TestLabel2=LabelValue2"] + set_module_args(args) + ignore1, ignore2, params = oc_zoscloudbroker.create_and_validate_module() + + labels = params["labels"] + assert ("TestLabel1" in labels and labels["TestLabel1"] == "LabelValue1") + assert ("TestLabel2" in labels and labels["TestLabel2"] == "LabelValue2") + + def test_module_fails_when_labels_arg_invalid(self): + with self.assertRaises(AnsibleFailJson) as result: + misshapenLabel = "This=Is=A=Misshapen=Label" + + args = {**self.mock_module_params} + args["labels"] = [misshapenLabel] + set_module_args(args) + oc_zoscloudbroker.create_and_validate_module() + + assert ( + error_equal( + result.exception.args[0]["msg"], + "Recieved label with misshapen form: '{}'. Each label in the list should take the \ + form 'key=value'.".format(misshapenLabel))) + + with self.assertRaises(AnsibleFailJson) as result: + misshapenLabel = "AMisshapenLabel" + + args["labels"] = [misshapenLabel] + set_module_args(args) + oc_zoscloudbroker.create_and_validate_module() + + assert ( + error_equal( + result.exception.args[0]["msg"], + "Recieved label with misshapen form: '{}'. Each label in the list should take the \ + form 'key=value'.".format(misshapenLabel))) diff --git a/ibm/operator_collection_sdk/tests/unit/requirements.txt b/ibm/operator_collection_sdk/tests/unit/requirements.txt new file mode 100644 index 00000000..d4a4e0aa --- /dev/null +++ b/ibm/operator_collection_sdk/tests/unit/requirements.txt @@ -0,0 +1,3 @@ +pytest +pyyaml +kubernetes \ No newline at end of file diff --git a/ibm/operator_collection_sdk/tests/unit/unit.sh b/ibm/operator_collection_sdk/tests/unit/unit.sh new file mode 100755 index 00000000..b509c8dd --- /dev/null +++ b/ibm/operator_collection_sdk/tests/unit/unit.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash + +# (c) Copyright IBM Corp. 2024 +# Apache License, Version 2.0 (see https://opensource.org/licenses/Apache-2.0) + +function parseCommandLine { + for arg in "$@"; do + case $arg in + -i=*|--install-collection=*) + install_collection=${arg#*=} + break + ;; + -i|--install-collection) + install_collection=true + break + ;; + *) + echo "Unrecognized option: $arg" + echo "Usage: [--install-collection=] (alias: [-i=]), default: true" + exit 1; + ;; + esac + done + + if [[ $(echo "${install_collection}" | tr '[:upper:]' '[:lower:]') == "true" ]]; then + install_collection=true + else + install_collection=false + fi +} + +install_collection=true +parseCommandLine "$@" + +if [[ "${install_collection}" == "true" ]]; then + cwd=$(pwd) + if [[ ${cwd} =~ "ibm/operator_collection_sdk" ]]; then + printf "\n\033[1;32m Installing collection locally... \033[00m" + collection_path=$(echo "${cwd}" | sed -e "s/ibm\/operator_collection_sdk.*$/ibm\/operator_collection_sdk/g") + ansible-galaxy collection install "${collection_path}" -f + else + echo -e "\n\033[1;31m Expected script to be run from somewhere within '~/**/ibm/operator_collection_sdk/*' instead got '${cwd}'\033[00m" + exit 1 + fi +fi + +# Run Unit Tests +cd ~/.ansible/collections/ansible_collections/ibm/operator_collection_sdk +ansible-test units -v --venv +exit_status="$?" + +if [[ ${exit_status} != 0 ]] \ +&& [[ $(echo "$VIRTUAL_ENV" | awk '{print length}') != 0 ]] \ +|| [[ -n "$VIRTUAL_ENV" ]]; then + echo -e "\n\033[1;31m Hint: Is your virtual environment still on? If so, try turning it off (deactivate). \033[00m" + echo -e '\033[1;31m "'"$VIRTUAL_ENV"'" \033[00m\n' + exit "$exit_status" +fi + +exit "$exit_status" \ No newline at end of file diff --git a/ibm/operator_collection_sdk/tests/unit/utils/__init__.py b/ibm/operator_collection_sdk/tests/unit/utils/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/ibm/operator_collection_sdk/tests/unit/utils/mock.py b/ibm/operator_collection_sdk/tests/unit/utils/mock.py new file mode 100644 index 00000000..1685f179 --- /dev/null +++ b/ibm/operator_collection_sdk/tests/unit/utils/mock.py @@ -0,0 +1,49 @@ +import json + +from ansible.module_utils import basic +from ansible.module_utils.common.text.converters import to_bytes + + +def error_equal(error1: str, error2: str) -> bool: + return str(error1).replace(" ", "") == str(error2).replace(" ", "") + + +def set_module_args(args, check_mode=False): + """prepare arguments so that they will be picked up during module creation""" + anisble_module_args = {"ANSIBLE_MODULE_ARGS": args} + if check_mode: + anisble_module_args["ANSIBLE_MODULE_ARGS"]["_ansible_check_mode"] = True + args = json.dumps(anisble_module_args) + basic._ANSIBLE_ARGS = to_bytes(args) + + +class AnsibleExitJson(Exception): + """Exception class to be raised by module.exit_json and caught by the test case""" + pass + + +class AnsibleFailJson(Exception): + """Exception class to be raised by module.fail_json and caught by the test case""" + pass + + +def exit_json(*args, **kwargs): + """function to patch over exit_json; package return data into an exception""" + if 'changed' not in kwargs: + kwargs['changed'] = False + raise AnsibleExitJson(kwargs) + + +def fail_json(*args, **kwargs): + """function to patch over fail_json; package return data into an exception""" + kwargs['failed'] = True + raise AnsibleFailJson(kwargs) + + +def get_bin_path(self, arg, required=False): + """Mock AnsibleModule.get_bin_path""" + if arg.endswith('my_command'): + return '/usr/bin/my_command' + else: + if required: + fail_json(msg='%r not found !' % arg) From 3e15d3b906240b4bd4337bb0ffe565c73c8fac36 Mon Sep 17 00:00:00 2001 From: Yemi Kelani Date: Fri, 3 May 2024 16:11:21 -0700 Subject: [PATCH 2/3] Fixed Ansible and Molecule test files. Signed-off-by: Yemi Kelani --- ibm/operator_collection_sdk/galaxy.yml | 74 ------------- .../playbooks/molecule/cluster_clean.yml | 2 +- .../playbooks/molecule/cluster_setup.yml | 2 +- .../create_operator_local/converge.yml | 101 +----------------- .../create_operator_local/destroy.yml | 79 +------------- .../create_operator_local/molecule.yml | 5 +- .../create_operator_local/prepare.yml | 3 - .../molecule/create_operator_local/verify.yml | 3 - .../converge.yml | 100 +---------------- .../destroy.yml | 89 +-------------- .../molecule.yml | 5 +- .../prepare.yml | 3 - .../verify.yml | 3 - .../tasks/main.yml | 63 ----------- .../tasks/set_vars.yml | 1 - .../tests/sanity/ignore-2.16.txt | 3 - .../unit/modules/test_oc_zoscloudbroker.py | 12 +-- 17 files changed, 32 insertions(+), 516 deletions(-) diff --git a/ibm/operator_collection_sdk/galaxy.yml b/ibm/operator_collection_sdk/galaxy.yml index 16f2ed1e..add91db9 100644 --- a/ibm/operator_collection_sdk/galaxy.yml +++ b/ibm/operator_collection_sdk/galaxy.yml @@ -70,77 +70,3 @@ build_ignore: # 'omit_default_directives' is a boolean that controls whether the default directives are used. Mutually exclusive # with 'build_ignore' # manifest: null - -### REQUIRED -# The namespace of the collection. This can be a company/brand/organization or product namespace under which all -# content lives. May only contain alphanumeric lowercase characters and underscores. Namespaces cannot start with -# underscores or numbers and cannot contain consecutive underscores -namespace: ibm - -# The name of the collection. Has the same character restrictions as 'namespace' -name: operator_collection_sdk - -# The version of the collection. Must be compatible with semantic versioning -version: 2.0.0-alpha.2 - -# The path to the Markdown (.md) readme file. This path is relative to the root of the collection -readme: README.md - -# A list of the collection's content authors. Can be just the name or in the format 'Full Name (url) -# @nicks:irc/im.site#channel' -authors: -- Latrell Freeman - - -### OPTIONAL but strongly recommended -# A short summary description of the collection -description: The IBM Operator Collection SDK provides the resources and tools that are needed to develop Operator Collections against the IBM® z/OS® Cloud Broker as part of the IBM Z® and Cloud Modernization Stack. - -# The path to the license file for the collection. This path is relative to the root of the collection. This key is -# mutually exclusive with 'license' -license_file: LICENSE - -# A list of tags you want to associate with the collection for indexing/searching. A tag name has the same character -# requirements as 'namespace' and 'name' -tags: - - ibm - - operator_collection - - operator_collection_sdk - - zos - - z_os - - z - -# Collections that this collection requires to be installed for it to be usable. The key of the dict is the -# collection label 'namespace.name'. The value is a version range -# L(specifiers,https://python-semanticversion.readthedocs.io/en/latest/#requirement-specification). Multiple version -# range specifiers can be set and are separated by ',' -dependencies: {} - -# The URL of the originating SCM repository -repository: https://github.com/IBM/operator-collection-sdk - -# The URL to any online docs -documentation: https://github.com/IBM/operator-collection-sdk/blob/main/ibm/operator_collection_sdk/README.md - -# The URL to the homepage of the collection/project -homepage: https://github.com/IBM/operator-collection-sdk/blob/main/ibm/operator_collection_sdk - -# The URL to the collection issue tracker -issues: https://github.com/IBM/operator-collection-sdk/issues - -# A list of file glob-like patterns used to filter any files or directories that should not be included in the build -# artifact. A pattern is matched from the relative path of the file or directory of the collection directory. This -# uses 'fnmatch' to match the files or directories. Some directories and files like 'galaxy.yml', '*.pyc', '*.retry', -# and '.git' are always filtered. Mutually exclusive with 'manifest' -build_ignore: - - .gitignore - - playbooks/molecule - - ansible_venv - -# A dict controlling use of manifest directives used in building the collection artifact. The key 'directives' is a -# list of MANIFEST.in style -# L(directives,https://packaging.python.org/en/latest/guides/using-manifest-in/#manifest-in-commands). The key -# 'omit_default_directives' is a boolean that controls whether the default directives are used. Mutually exclusive -# with 'build_ignore' -# manifest: null - diff --git a/ibm/operator_collection_sdk/playbooks/molecule/cluster_clean.yml b/ibm/operator_collection_sdk/playbooks/molecule/cluster_clean.yml index 56c7666e..ff413a54 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/cluster_clean.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/cluster_clean.yml @@ -9,7 +9,7 @@ connection: local gather_facts: false tasks: - - name: Install dependency # necessary for gh-actions use + - name: Install dependency # necessary for gh-actions ansible tests pip: name: - kubernetes diff --git a/ibm/operator_collection_sdk/playbooks/molecule/cluster_setup.yml b/ibm/operator_collection_sdk/playbooks/molecule/cluster_setup.yml index 320d7cf9..47de5410 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/cluster_setup.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/cluster_setup.yml @@ -9,7 +9,7 @@ connection: local gather_facts: false tasks: - - name: Install dependency # necessary for gh-actions use + - name: Install dependency # necessary for gh-actions ansible tests pip: name: - kubernetes diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/converge.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/converge.yml index e0f99af7..4380a8e4 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/converge.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/converge.yml @@ -4,101 +4,8 @@ # --- -- name: Converge - hosts: all - connection: local - gather_facts: false - vars: - ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" - - tasks: - - name: Create Namespace - kubernetes.core.k8s: - state: present - definition: - kind: Namespace - metadata: - name: "{{ ocpnamespace }}" - - - name: Create OperatorGroup - kubernetes.core.k8s: - state: present - definition: - apiVersion: operators.coreos.com/v1 - kind: OperatorGroup - metadata: - name: "{{ ocpnamespace }}" - namespace: "{{ ocpnamespace }}" - spec: - targetNamespaces: - - "{{ ocpnamespace }}" - upgradeStrategy: Default - - - name: Create Subscripton - kubernetes.core.k8s: - state: present - definition: - apiVersion: operators.coreos.com/v1alpha1 - kind: Subscription - metadata: - name: "{{ subscription_name }}" - namespace: "{{ ocpnamespace }}" - spec: - channel: v2.2 - installPlanApproval: Automatic - name: ibm-zoscb - source: ibm-operator-catalog - sourceNamespace: openshift-marketplace - startingCSV: "{{ zoscb_release }}" - - - name: Validate Subscription installed successfully - kubernetes.core.k8s_info: - api_version: operators.coreos.com/v1alpha1 - kind: Subscription - name: "{{ subscription_name }}" - namespace: "{{ ocpnamespace }}" - register: subscription_results - until: "subscription_results.resources[0].status.installedCSV is defined and subscription_results.resources[0].status.currentCSV" - retries: 30 - delay: 5 - - - name: Validate CSV installed successfully - kubernetes.core.k8s_info: - api_version: operators.coreos.com/v1alpha1 - kind: ClusterServiceVersion - name: "{{ subscription_results.resources[0].status.installedCSV }}" - namespace: "{{ ocpnamespace }}" - register: csv_results - until: "csv_results.resources[0].status.phase is defined and csv_results.resources[0].status.phase == 'Succeeded'" - retries: 30 - delay: 5 +- name: Set up test environment + import_playbook: ../cluster_setup.yml - - name: Create ZosCloudBroker - ibm.operator_collection_sdk.oc_zoscloudbroker: - state: present - namespace: "{{ ocpnamespace }}" - accept_license: true - multi_namespace: true - log_level: trace - storage: - configure: false - enabled: false - storage_size: 5Gi - volume_mode: Filesystem - - - name: Validate ZosCloudBroker installed successfully - kubernetes.core.k8s_info: - api_version: zoscb.ibm.com/v2beta1 - kind: ZosCloudBroker - name: "{{ zoscloudbroker_name }}" - namespace: "{{ ocpnamespace }}" - register: zoscb_results - until: "zoscb_results.resources[0].status.phase == 'Successful'" - retries: 30 - delay: 5 - - -- import_playbook: ../../create_operator.yml - vars: - filepath: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../examples/racf-operator" - ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" +- name: Converge + import_playbook: ../../create_operator.yml diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/destroy.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/destroy.yml index 3132bf3d..7b493920 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/destroy.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/destroy.yml @@ -8,87 +8,16 @@ import_playbook: ../../delete_operator.yml vars: filepath: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../examples/racf-operator" - ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" + +- name: Clean test environment + import_playbook: ../cluster_clean.yml + - name: Destroy hosts: localhost connection: local gather_facts: false no_log: "{{ molecule_no_log }}" - vars: - ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" - tasks: - - name: Get SubOperatorConfigs - kubernetes.core.k8s_info: - api_version: zoscb.ibm.com/v2beta2 - kind: SubOperatorConfig - namespace: "{{ target_namespace }}" - register: soc_results - - - name: Remove Orphaned SubOperatorConfigs - kubernetes.core.k8s_json_patch: - api_version: zoscb.ibm.com/v2beta2 - kind: SubOperatorConfig - namespace: "{{ target_namespace }}" - name: "{{ item.metadata.name }}" - patch: - - op: replace - path: /metadata/finalizers - value: [] - when: soc_results.resources | length > 0 - with_items: "{{ soc_results.resources }}" - - - name: Delete ZosEndpoint - kubernetes.core.k8s: - state: absent - api_version: zoscb.ibm.com/v2beta2 - kind: ZosEndpoint - name: "{{ zosendpoint_name }}" - namespace: "{{ ocpnamespace }}" - wait: true - wait_sleep: 5 - wait_timeout: 140 - - - name: Delete ZosCloudBoker - kubernetes.core.k8s: - state: absent - api_version: zoscb.ibm.com/v2beta1 - kind: ZosCloudBroker - name: "{{ zoscloudbroker_name }}" - namespace: "{{ ocpnamespace }}" - wait: true - wait_sleep: 5 - wait_timeout: 140 - - - name: Delete Subscripton - kubernetes.core.k8s: - state: absent - api_version: operators.coreos.com/v1alpha1 - kind: Subscription - name: "{{ subscription_name }}" - namespace: "{{ ocpnamespace }}" - wait: true - wait_sleep: 5 - wait_timeout: 140 - - - name: Delete OperatorGroup - kubernetes.core.k8s: - state: absent - api_version: operators.coreos.com/v1 - kind: OperatorGroup - name: "{{ ocpnamespace }}" - namespace: "{{ ocpnamespace }}" - - - name: Delete Namespace - kubernetes.core.k8s: - state: absent - kind: Namespace - name: "{{ ocpnamespace }}" - wait: true - wait_sleep: 5 - wait_timeout: 140 - ignore_errors: true - - name: Remove local build ansible.builtin.file: path: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../examples/racf-operator/local" diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/molecule.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/molecule.yml index c976d82e..798df40d 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/molecule.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/molecule.yml @@ -15,6 +15,8 @@ provisioner: config_options: defaults: jinja2_native: true + playbooks: + cleanup: cleanup.yml ## extra-vars needed to bypass vars_prompts ansible_args: @@ -26,7 +28,8 @@ provisioner: collection_namespace: ibm subscription_name: ibm-zoscb zoscloudbroker_name: zoscloudbroker - ocpNamespace: ${OCP_NAMESPACE:-molecule} + ocpnamespace: "{{ '${OCP_NAMESPACE:-molecule}' | lower | regex_replace('[^-a-zA-Z0-9]','-') }}" + operator_path: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../examples/racf-operator" zosendpoint_name: ibmcloud-vm openshift_token: ${OPENSHIFT_TOKEN} openshift_server: ${OPENSHIFT_SERVER} diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/prepare.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/prepare.yml index 509f6e25..1c835d53 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/prepare.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/prepare.yml @@ -8,9 +8,6 @@ hosts: all connection: local gather_facts: false - vars: - ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" - tasks: - name: Validate OCP cluster authorization ansible.builtin.command: oc project diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/verify.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/verify.yml index 598821e3..7a6e7f82 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/verify.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_operator_local/verify.yml @@ -8,9 +8,6 @@ hosts: all connection: local gather_facts: false - vars: - ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" - tasks: - name: Validate ZosEndpoint kubernetes.core.k8s_info: diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/converge.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/converge.yml index b1b738e2..70c4a97d 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/converge.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/converge.yml @@ -8,111 +8,19 @@ hosts: all connection: local gather_facts: false - vars: - ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" - - tasks: - - name: Create Namespace - kubernetes.core.k8s: - state: present - definition: - kind: Namespace - metadata: - name: "{{ ocpnamespace }}" - - - name: Create OperatorGroup - kubernetes.core.k8s: - state: present - definition: - apiVersion: operators.coreos.com/v1 - kind: OperatorGroup - metadata: - name: "{{ ocpnamespace }}" - namespace: "{{ ocpnamespace }}" - spec: - targetNamespaces: - - "{{ ocpnamespace }}" - upgradeStrategy: Default - - - name: Create Subscripton - kubernetes.core.k8s: - state: present - definition: - apiVersion: operators.coreos.com/v1alpha1 - kind: Subscription - metadata: - name: "{{ subscription_name }}" - namespace: "{{ ocpnamespace }}" - spec: - channel: v2.2 - installPlanApproval: Automatic - name: ibm-zoscb - source: ibm-operator-catalog - sourceNamespace: openshift-marketplace - startingCSV: "{{ zoscb_release }}" - - - name: Validate Subscription installed successfully - kubernetes.core.k8s_info: - api_version: operators.coreos.com/v1alpha1 - kind: Subscription - name: "{{ subscription_name }}" - namespace: "{{ ocpnamespace }}" - register: subscription_results - until: "subscription_results.resources[0].status.installedCSV is defined and subscription_results.resources[0].status.currentCSV" - retries: 30 - delay: 5 - - - name: Validate CSV installed successfully - kubernetes.core.k8s_info: - api_version: operators.coreos.com/v1alpha1 - kind: ClusterServiceVersion - name: "{{ subscription_results.resources[0].status.installedCSV }}" - namespace: "{{ ocpnamespace }}" - register: csv_results - until: "csv_results.resources[0].status.phase is defined and csv_results.resources[0].status.phase == 'Succeeded'" - retries: 30 - delay: 5 - - - name: Create ZosCloudBroker - ibm.operator_collection_sdk.oc_zoscloudbroker: - state: present - namespace: "{{ ocpnamespace }}" - accept_license: true - multi_namespace: true - log_level: trace - storage: - configure: false - enabled: false - storage_size: 5Gi - volume_mode: Filesystem - - - name: Validate ZosCloudBroker installed successfully - kubernetes.core.k8s_info: - api_version: zoscb.ibm.com/v2beta1 - kind: ZosCloudBroker - name: "{{ zoscloudbroker_name }}" - namespace: "{{ ocpnamespace }}" - register: zoscb_results - until: "zoscb_results.resources[0].status.phase == 'Successful'" - retries: 30 - delay: 5 +- import_playbook: ../cluster_setup.yml - import_playbook: ../../create_operator.yml vars: - filepath: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../examples/racf-operator" - ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" + filepath: "{{ operator_path }}" - import_playbook: ../../create_credential_secret.yml - vars: - ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" - import_playbook: ../../redeploy_operator.yml vars: - filepath: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../examples/racf-operator" - ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" + filepath: "{{ operator_path }}" - import_playbook: ../../redeploy_collection.yml vars: - filepath: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../examples/racf-operator" - ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" \ No newline at end of file + filepath: "{{ operator_path }}" \ No newline at end of file diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/destroy.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/destroy.yml index 4aa3537c..7b493920 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/destroy.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/destroy.yml @@ -8,97 +8,16 @@ import_playbook: ../../delete_operator.yml vars: filepath: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../examples/racf-operator" - ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" + +- name: Clean test environment + import_playbook: ../cluster_clean.yml + - name: Destroy hosts: localhost connection: local gather_facts: false no_log: "{{ molecule_no_log }}" - vars: - ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" - tasks: - - name: Get SubOperatorConfigs - kubernetes.core.k8s_info: - api_version: zoscb.ibm.com/v2beta2 - kind: SubOperatorConfig - namespace: "{{ target_namespace }}" - register: soc_results - - - name: Remove Orphaned SubOperatorConfigs - kubernetes.core.k8s_json_patch: - api_version: zoscb.ibm.com/v2beta2 - kind: SubOperatorConfig - namespace: "{{ target_namespace }}" - name: "{{ item.metadata.name }}" - patch: - - op: replace - path: /metadata/finalizers - value: [] - when: soc_results.resources | length > 0 - with_items: "{{ soc_results.resources }}" - - - name: Delete test secret - kubernetes.core.k8s: - state: absent - kind: secret - name: "{{ secret_name }}" - namespace: "{{ ocpnamespace }}" - wait: true - wait_sleep: 5 - wait_timeout: 140 - - - name: Delete ZosEndpoint - kubernetes.core.k8s: - state: absent - api_version: zoscb.ibm.com/v2beta2 - kind: ZosEndpoint - name: "{{ zosendpoint_name }}" - namespace: "{{ ocpnamespace }}" - wait: true - wait_sleep: 5 - wait_timeout: 140 - - - name: Delete ZosCloudBoker - kubernetes.core.k8s: - state: absent - api_version: zoscb.ibm.com/v2beta1 - kind: ZosCloudBroker - name: "{{ zoscloudbroker_name }}" - namespace: "{{ ocpnamespace }}" - wait: true - wait_sleep: 5 - wait_timeout: 140 - - - name: Delete Subscripton - kubernetes.core.k8s: - state: absent - api_version: operators.coreos.com/v1alpha1 - kind: Subscription - name: "{{ subscription_name }}" - namespace: "{{ ocpnamespace }}" - wait: true - wait_sleep: 5 - wait_timeout: 140 - - - name: Delete OperatorGroup - kubernetes.core.k8s: - state: absent - api_version: operators.coreos.com/v1 - kind: OperatorGroup - name: "{{ ocpnamespace }}" - namespace: "{{ ocpnamespace }}" - - - name: Delete Namespace - kubernetes.core.k8s: - state: absent - kind: Namespace - name: "{{ ocpnamespace }}" - wait: true - wait_sleep: 5 - wait_timeout: 140 - ignore_errors: true - - name: Remove local build ansible.builtin.file: path: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../examples/racf-operator/local" diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/molecule.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/molecule.yml index ec785725..be2f34ea 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/molecule.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/molecule.yml @@ -15,6 +15,8 @@ provisioner: config_options: defaults: jinja2_native: true + playbooks: + cleanup: cleanup.yml ## extra-vars needed to bypass vars_prompts ansible_args: @@ -26,7 +28,8 @@ provisioner: collection_namespace: ibm subscription_name: ibm-zoscb zoscloudbroker_name: zoscloudbroker - ocpNamespace: ${OCP_NAMESPACE:-molecule} + ocpnamespace: "{{ '${OCP_NAMESPACE:-molecule}' | lower | regex_replace('[^-a-zA-Z0-9]','-') }}" + operator_path: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../examples/racf-operator" zosendpoint_name: ibmcloud-vm secret_name: "test-secret" openshift_token: ${OPENSHIFT_TOKEN} diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/prepare.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/prepare.yml index 509f6e25..1c835d53 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/prepare.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/prepare.yml @@ -8,9 +8,6 @@ hosts: all connection: local gather_facts: false - vars: - ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" - tasks: - name: Validate OCP cluster authorization ansible.builtin.command: oc project diff --git a/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/verify.yml b/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/verify.yml index a50220c5..4ef6c9a0 100644 --- a/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/verify.yml +++ b/ibm/operator_collection_sdk/playbooks/molecule/create_redeploy_delete_operator/verify.yml @@ -8,9 +8,6 @@ hosts: all connection: local gather_facts: false - vars: - ocpnamespace: "{{ ocpNamespace | lower | replace('_','-') | replace('/','-') }}" - tasks: - name: Validate ZosEndpoint kubernetes.core.k8s_info: diff --git a/ibm/operator_collection_sdk/roles/upload_collection_to_manager/tasks/main.yml b/ibm/operator_collection_sdk/roles/upload_collection_to_manager/tasks/main.yml index 68ede150..97471420 100644 --- a/ibm/operator_collection_sdk/roles/upload_collection_to_manager/tasks/main.yml +++ b/ibm/operator_collection_sdk/roles/upload_collection_to_manager/tasks/main.yml @@ -69,66 +69,3 @@ - name: Copy local build to manager pod using new collection path ansible.builtin.command: oc cp {{ find_result.files[0].path }} "{{ pod_results.resources[0].metadata.namespace }}/{{ pod_results.resources[0].metadata.name }}":/opt/collections/suboperator/{{ operator_name }}/{{ operator_version }}/{{ find_result.files[0].path | basename }} when: soc_results.resources | length == 0 or (redeploy is defined and redeploy is true) -# -# Copyright 2023 IBM Inc. All rights reserved -# SPDX-License-Identifier: Apache2.0 -# - ---- -- name: Get Manager Pod Name - kubernetes.core.k8s_info: - kind: Pod - namespace: "{{ namespace }}" - label_selectors: - - component = manager - register: pod_results - -- name: Validate manager pod exists - ansible.builtin.fail: - msg: "Manager pod doesn't exist or multiple manager pods listed in namespace" - when: pod_results.resources | length == 0 or pod_results.resources | length > 1 - -- name: Get collection filepath - ansible.builtin.find: - paths: "{{ path }}/local/builds/{{ operator_version }}" - register: find_result - -- name: Get SubOperatorConfig - kubernetes.core.k8s_info: - api_version: zoscb.ibm.com/v2beta2 - kind: SubOperatorConfig - namespace: "{{ namespace }}" - label_selectors: - - "operator-name = {{ operator_name }}" - register: soc_results - -- name: Validate SubOperatorConfig exists - ansible.builtin.debug: - msg: "SubOperatorConfig doesn't exist or multiple SubOperatorConfigs listed in namespace" - when: soc_results.resources | length == 0 or soc_results.resources | length > 1 - -- name: Get collection file path in manager Pod - kubernetes.core.k8s_info: - api_version: zoscb.ibm.com/v2beta2 - kind: OperatorCollection - name: "{{ soc_results.resources[0].spec.operatorCollection }}" - namespace: "{{ namespace }}" - register: oc_results - when: soc_results.resources | length > 0 - -- name: Validate OperatorCollection exists - ansible.builtin.fail: - msg: "OperatorCollection doesn't exist" - when: soc_results.resources | length > 0 and oc_results.resources | length == 0 - -- name: Copy local build to manager pod using existing collection path - ansible.builtin.command: oc cp {{ find_result.files[0].path }} "{{ pod_results.resources[0].metadata.namespace }}/{{ pod_results.resources[0].metadata.name }}":"{{ oc_results.resources[0].status.config.collectionPath }}" - when: soc_results.resources | length > 0 and oc_results.resources | length > 0 and (redeploy is not defined or redeploy is false) - -- name: Create directory on pod if doesn't exist - ansible.builtin.command: oc exec -i -n "{{ pod_results.resources[0].metadata.namespace }}" "{{ pod_results.resources[0].metadata.name }}" -- mkdir -p /opt/collections/suboperator/{{ operator_name }}/{{ operator_version }} - when: soc_results.resources | length == 0 and (redeploy is not defined or redeploy is false) - -- name: Copy local build to manager pod using new collection path - ansible.builtin.command: oc cp {{ find_result.files[0].path }} "{{ pod_results.resources[0].metadata.namespace }}/{{ pod_results.resources[0].metadata.name }}":/opt/collections/suboperator/{{ operator_name }}/{{ operator_version }}/{{ find_result.files[0].path | basename }} - when: soc_results.resources | length == 0 or (redeploy is defined and redeploy is true) diff --git a/ibm/operator_collection_sdk/roles/upload_collection_to_manager/tasks/set_vars.yml b/ibm/operator_collection_sdk/roles/upload_collection_to_manager/tasks/set_vars.yml index 749447f9..8a7511b1 100644 --- a/ibm/operator_collection_sdk/roles/upload_collection_to_manager/tasks/set_vars.yml +++ b/ibm/operator_collection_sdk/roles/upload_collection_to_manager/tasks/set_vars.yml @@ -42,4 +42,3 @@ operator_name: "{{ operator_config.name | lower }}" operator_version: "{{ operator_config.version }}" when: operator_name is undefined or operator_version is undefined - diff --git a/ibm/operator_collection_sdk/tests/sanity/ignore-2.16.txt b/ibm/operator_collection_sdk/tests/sanity/ignore-2.16.txt index 8deead41..47791684 100644 --- a/ibm/operator_collection_sdk/tests/sanity/ignore-2.16.txt +++ b/ibm/operator_collection_sdk/tests/sanity/ignore-2.16.txt @@ -1,10 +1,7 @@ -<<<<<<< HEAD -======= plugins/modules/oc_zoscloudbroker.py validate-modules:parameter-type-not-in-doc # "enabled" var is erroneously flagged plugins/modules/oc_zoscloudbroker.py validate-modules:undocumented-parameter # "enabled" var is erroneously flagged plugins/modules/oc_zoscloudbroker.py validate-modules:return-syntax-error # "metadata" return field varies wildly, can't document plugins/modules/oc_zoscloudbroker.py validate-modules:missing-gplv3-license # ignore gplv3 license, we use apache ->>>>>>> v2-cloudbroker playbooks/templates/endpoint.yml yamllint!skip playbooks/templates/suboperatorconfig.yml yamllint!skip playbooks/templates/operatorcollection.yml yamllint!skip \ No newline at end of file diff --git a/ibm/operator_collection_sdk/tests/unit/modules/test_oc_zoscloudbroker.py b/ibm/operator_collection_sdk/tests/unit/modules/test_oc_zoscloudbroker.py index 3e5adcd1..965a64cd 100644 --- a/ibm/operator_collection_sdk/tests/unit/modules/test_oc_zoscloudbroker.py +++ b/ibm/operator_collection_sdk/tests/unit/modules/test_oc_zoscloudbroker.py @@ -125,10 +125,10 @@ def test_module_validates_and_constructs_valid_labels_arg(self): def test_module_fails_when_labels_arg_invalid(self): with self.assertRaises(AnsibleFailJson) as result: - misshapenLabel = "This=Is=A=Misshapen=Label" + misshapen_label = "This=Is=A=Misshapen=Label" args = {**self.mock_module_params} - args["labels"] = [misshapenLabel] + args["labels"] = [misshapen_label] set_module_args(args) oc_zoscloudbroker.create_and_validate_module() @@ -136,12 +136,12 @@ def test_module_fails_when_labels_arg_invalid(self): error_equal( result.exception.args[0]["msg"], "Recieved label with misshapen form: '{}'. Each label in the list should take the \ - form 'key=value'.".format(misshapenLabel))) + form 'key=value'.".format(misshapen_label))) with self.assertRaises(AnsibleFailJson) as result: - misshapenLabel = "AMisshapenLabel" + misshapen_label = "AMisshapenLabel" - args["labels"] = [misshapenLabel] + args["labels"] = [misshapen_label] set_module_args(args) oc_zoscloudbroker.create_and_validate_module() @@ -149,4 +149,4 @@ def test_module_fails_when_labels_arg_invalid(self): error_equal( result.exception.args[0]["msg"], "Recieved label with misshapen form: '{}'. Each label in the list should take the \ - form 'key=value'.".format(misshapenLabel))) + form 'key=value'.".format(misshapen_label))) From b90c3a36c9f1c08ffef9a4fbd20b57aabbe4d4a6 Mon Sep 17 00:00:00 2001 From: Yemi Kelani Date: Mon, 6 May 2024 10:12:33 -0700 Subject: [PATCH 3/3] Test readme updated. Signed-off-by: Yemi Kelani --- ibm/operator_collection_sdk/tests/README.md | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/ibm/operator_collection_sdk/tests/README.md b/ibm/operator_collection_sdk/tests/README.md index 669395cd..8ab024c8 100644 --- a/ibm/operator_collection_sdk/tests/README.md +++ b/ibm/operator_collection_sdk/tests/README.md @@ -1,4 +1,5 @@ ### Running Tests Locally + --- > This document does not cover molecule testing. @@ -8,36 +9,45 @@ Test scripts can be run from anywhere within the collection, given the current w By default, the tests will install the codebase/collection locally. This functionality can be configured with the following flags:`-i` / `--install-collection` which can be set either `true` or `false`, i.e. `--install-collection=false`. -Usage: +Usage: + - `--install-collection=`, default: `true` - Alias: `-i=` **Quick Start:** + 1. Navigate to `~/**/ibm/operator_collection_sdk/*`. 2. Deactivate your virtual environment (if it is active). 3. Run a test script. + --- #### Unit Tests + To install the collection and run all unit tests: + ```bash -chmod +x ./tests/unit/unit.sh ./tests/unit/unit.sh ``` + --- #### Sanity Tests + To install the collection and run sanity tests: + ```bash -chmod +x ./tests/unit/unit.sh ./tests/unit/unit.sh ``` + --- #### Integration Tests + To install the collection and run all Integration tests: + ```bash -chmod +x ./tests/integration/integration.sh ./tests/integration/integration.sh ``` -Note: This test will set up and teardown a cluster environment too. \ No newline at end of file + +Note: This test will set up and teardown a cluster environment too, so you must be logged in and connected to a cluster. \ No newline at end of file