From d063d44b7322b160d72e03d2185f2a60b1828877 Mon Sep 17 00:00:00 2001 From: Yusuke Tsutsumi Date: Tue, 13 Dec 2022 06:17:00 +0000 Subject: [PATCH] fixing gcp_resourcemanager_project delete gcp_resourcemanager_project was not properly deleting projects. fixing gcp_resourcemanager_project as well. fixes #530. --- .../workflows/ansible-integration-tests.yml | 4 +- CONTRIBUTING.md | 4 +- .../modules/gcp_resourcemanager_project.py | 6 +- .../gcp_resourcemanager_project_info.py | 15 ++++- scripts/cleanup-project.sh | 9 +++ .../tasks/autogen.yml | 56 +++++++++++-------- 6 files changed, 64 insertions(+), 30 deletions(-) diff --git a/.github/workflows/ansible-integration-tests.yml b/.github/workflows/ansible-integration-tests.yml index fbd44e6e..7fb920f6 100644 --- a/.github/workflows/ansible-integration-tests.yml +++ b/.github/workflows/ansible-integration-tests.yml @@ -6,6 +6,7 @@ on: env: GCP_SERVICE_ACCOUNT: "github-ci@ansible-gcp-ci.iam.gserviceaccount.com" GCP_PROJECT: "ansible-gcp-ci" + GCP_FOLDER_ID: "542027184392" jobs: integration: # NOTE: GitHub does not allow secrets to be used @@ -44,6 +45,7 @@ jobs: gcp_cred_file: /tmp/service-account-key.json gcp_cred_kind: serviceaccount gcp_cred_email: $GCP_SERVICE_ACCOUNT + gcp_folder_id: $GCP_FOLDER_ID " > ./tests/integration/cloud-config-gcp.ini # cleanup test environment - name: Auth to Gcloud @@ -58,7 +60,7 @@ jobs: - name: Run cleanup run: | ./scripts/bootstrap-project.sh $GCP_PROJECT $GCP_SERVICE_ACCOUNT - ./scripts/cleanup-project.sh $GCP_PROJECT $GCP_SERVICE_ACCOUNT + ./scripts/cleanup-project.sh $GCP_PROJECT $GCP_FOLDER_ID # run tests - name: Run integration tests # Add the -vvv flag to print out more output diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 79f6cb57..716d767c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -40,6 +40,7 @@ gcp_project: @PROJECT_ID gcp_cred_file: @CRED_FILE gcp_cred_kind: @CRED_KIND gcp_cred_email: @EMAIL +gcp_folder_id: @TEST_FOLDER (to create test projects) ``` #### Setting up the project for testing @@ -97,5 +98,4 @@ the codebase. ### Updating the supported ansible-core version 1. modify the [ansible-integration-tests.yaml](.github/workflows/ansible-integration-tests.yml) to the version of ansible-core that you would like to test against. -1. (optional) update the version of ansible-core version required in [meta/runtime.yaml](meta/runtime.yml). - +1. (optional) update the version of ansible-core version required in [meta/runtime.yaml](meta/runtime.yml). \ No newline at end of file diff --git a/plugins/modules/gcp_resourcemanager_project.py b/plugins/modules/gcp_resourcemanager_project.py index 9cae5f05..045ec6ee 100644 --- a/plugins/modules/gcp_resourcemanager_project.py +++ b/plugins/modules/gcp_resourcemanager_project.py @@ -203,6 +203,8 @@ id: type: str ''' +ACTIVE = "ACTIVE" + ################################################################################ # Imports ################################################################################ @@ -250,7 +252,7 @@ def main(): update(module, self_link(module)) fetch = fetch_resource(module, self_link(module)) changed = True - else: + elif fetch.get("lifecycleState") == ACTIVE: delete(module, self_link(module)) fetch = {} changed = True @@ -375,7 +377,7 @@ def async_op_url(module, extra_data=None): def wait_for_operation(module, response): op_result = return_if_object(module, response) - if op_result is None: + if not op_result: return {} status = navigate_hash(op_result, ['done']) wait_done = wait_for_completion(status, op_result, module) diff --git a/plugins/modules/gcp_resourcemanager_project_info.py b/plugins/modules/gcp_resourcemanager_project_info.py index ab7981e3..a803b646 100644 --- a/plugins/modules/gcp_resourcemanager_project_info.py +++ b/plugins/modules/gcp_resourcemanager_project_info.py @@ -77,6 +77,11 @@ options: - This should not be set unless you know what you're doing. - This only alters the User Agent string for any API requests. type: str + page_size: + description: + - Indicates the number of projects that should be returned by the API + request + type: str notes: - for authentication, you can set service_account_file using the C(GCP_SERVICE_ACCOUNT_FILE) env variable. @@ -96,6 +101,7 @@ EXAMPLES = ''' project: test_project auth_kind: serviceaccount service_account_file: "/tmp/auth.pem" + page_size: 100 ''' RETURN = ''' @@ -175,7 +181,9 @@ import json def main(): - module = GcpModule(argument_spec=dict()) + module = GcpModule(argument_spec=dict( + page_size=dict(type='int') + )) if not module.params['scopes']: module.params['scopes'] = ['https://www.googleapis.com/auth/cloud-platform'] @@ -190,7 +198,10 @@ def collection(module): def fetch_list(module, link): auth = GcpSession(module, 'resourcemanager') - return auth.list(link, return_if_object, array_name='projects') + params = {} + if "page_size" in module.params: + params["pageSize"] = module.params.get("page_size") + return auth.list(link, return_if_object, array_name='projects', params=params) def return_if_object(module, response): diff --git a/scripts/cleanup-project.sh b/scripts/cleanup-project.sh index 8c78e5fa..21f9e460 100755 --- a/scripts/cleanup-project.sh +++ b/scripts/cleanup-project.sh @@ -8,6 +8,7 @@ # - google-cloud-sdk (gcloudgcloud ) set -e PROJECT_ID="${1}" +FOLDER_ID="${2}" # service account is unused today # SERVICE_ACCOUNT_NAME="${2}" ZONE="us-central1-a" @@ -28,6 +29,9 @@ main() { cleanup_resource "compute" "backend-services" "--global" "--global" cleanup_resource "compute" "backend-services" \ "--regions=us-central1" "--region=us-central1" + for resource in $(gcloud projects list --filter="parent.id:$FOLDER_ID" --format="csv[no-heading](PROJECT_ID)"); do + gcloud projects delete "${resource}" -q + done } cleanup_resource() { @@ -35,9 +39,14 @@ cleanup_resource() { resource="$2" extra_list_arg="$3" extra_delete_arg="$4" +<<<<<<< HEAD for resource_id in $(gcloud "${resource_group}" "${resource}" list --project="${PROJECT_ID}" --format="csv[no-heading](name)" "${extra_list_arg}"); do gcloud "${resource_group}" "${resource}" delete "${resource_id}" --project="${PROJECT_ID}" -q "${extra_delete_arg}" +======= + for resource in $(gcloud "${resource_group}" "${resource}" list --project="${PROJECT_ID}" --format="csv[no-heading](name)" "${extra_list_arg}"); do + gcloud "${resource_group}" "${resource}" delete "${resource}" --project="${PROJECT_ID}" -q "${extra_delete_arg}" +>>>>>>> 78c2743 (fixing gcp_resourcemanager_project delete) done } diff --git a/tests/integration/targets/gcp_resourcemanager_project/tasks/autogen.yml b/tests/integration/targets/gcp_resourcemanager_project/tasks/autogen.yml index 5e02c413..539b3ace 100644 --- a/tests/integration/targets/gcp_resourcemanager_project/tasks/autogen.yml +++ b/tests/integration/targets/gcp_resourcemanager_project/tasks/autogen.yml @@ -15,52 +15,57 @@ # Pre-test setup - name: delete a project google.cloud.gcp_resourcemanager_project: - name: My Sample Project - id: ansible-test-{{ 10000000000 | random }} + name: "{{ resource_prefix[0:30] }}" + id: "{{ resource_prefix[0:30] }}" auth_kind: "{{ gcp_cred_kind }}" service_account_file: "{{ gcp_cred_file }}" parent: - type: organization - id: 636173955921 + type: folder + id: "{{ gcp_folder_id }}" state: absent #---------------------------------------------------------- - name: create a project google.cloud.gcp_resourcemanager_project: - name: My Sample Project - id: ansible-test-{{ 10000000000 | random }} + name: "{{ resource_prefix[0:30] }}" + id: "{{ resource_prefix[0:30] }}" auth_kind: "{{ gcp_cred_kind }}" service_account_file: "{{ gcp_cred_file }}" parent: - type: organization - id: 636173955921 + type: folder + id: "{{ gcp_folder_id }}" state: present register: result - name: assert changed is true assert: that: - result.changed == true +- name: Pause for 2 minutes for project to appear + ansible.builtin.pause: + minutes: 2 - name: verify that project was created google.cloud.gcp_resourcemanager_project_info: project: "{{ gcp_project }}" auth_kind: "{{ gcp_cred_kind }}" service_account_file: "{{ gcp_cred_file }}" + # choose 1000 projects so iterate past the deleted ones. + page_size: 1000 scopes: - https://www.googleapis.com/auth/cloud-platform register: results - name: verify that command succeeded assert: that: - - results['resources'] | map(attribute='name') | select("match", ".*My Sample Project.*") | list | length == 1 + - results['resources'] | selectattr("lifecycleState", "equalto", "ACTIVE") | map(attribute='name') | select("match", ".*{{ resource_prefix[0:30] }}.*") | list | length == 1 # ---------------------------------------------------------------------------- - name: create a project that already exists google.cloud.gcp_resourcemanager_project: - name: My Sample Project - id: ansible-test-{{ 10000000000 | random }} + name: "{{ resource_prefix[0:30] }}" + id: "{{ resource_prefix[0:30] }}" auth_kind: "{{ gcp_cred_kind }}" service_account_file: "{{ gcp_cred_file }}" parent: - type: organization - id: 636173955921 + type: folder + id: "{{ gcp_folder_id }}" state: present register: result - name: assert changed is false @@ -70,41 +75,46 @@ #---------------------------------------------------------- - name: delete a project google.cloud.gcp_resourcemanager_project: - name: My Sample Project - id: ansible-test-{{ 10000000000 | random }} + name: "{{ resource_prefix[0:30] }}" + id: "{{ resource_prefix[0:30] }}" auth_kind: "{{ gcp_cred_kind }}" service_account_file: "{{ gcp_cred_file }}" parent: - type: organization - id: 636173955921 + type: folder + id: "{{ gcp_folder_id }}" state: absent register: result - name: assert changed is true assert: that: - result.changed == true +- name: Pause for 2 minutes for project to appear + ansible.builtin.pause: + minutes: 2 - name: verify that project was deleted google.cloud.gcp_resourcemanager_project_info: - project: "{{ gcp_project }}" + project: "{{ resource_prefix[0:30] }}" auth_kind: "{{ gcp_cred_kind }}" service_account_file: "{{ gcp_cred_file }}" + # choose 1000 projects so iterate past the deleted ones. + page_size: 1000 scopes: - https://www.googleapis.com/auth/cloud-platform register: results - name: verify that command succeeded assert: that: - - results['resources'] | map(attribute='name') | select("match", ".*My Sample Project.*") | list | length == 0 + - results['resources'] | selectattr("lifecycleState", "equalto", "DELETE_REQUESTED") | map(attribute='name') | select("match", ".*{{ resource_prefix[0:30] }}.*") | list | length == 1 # ---------------------------------------------------------------------------- - name: delete a project that does not exist google.cloud.gcp_resourcemanager_project: - name: My Sample Project - id: ansible-test-{{ 10000000000 | random }} + name: "{{ resource_prefix[0:30] }}" + id: "{{ resource_prefix[0:30] }}" auth_kind: "{{ gcp_cred_kind }}" service_account_file: "{{ gcp_cred_file }}" parent: - type: organization - id: 636173955921 + type: folder + id: "{{ gcp_folder_id }}" state: absent register: result - name: assert changed is false