fixing gcp_resourcemanager_project delete

gcp_resourcemanager_project was not properly deleting projects.

fixing gcp_resourcemanager_project as well.

fixes #530.
This commit is contained in:
Yusuke Tsutsumi 2022-12-13 06:17:00 +00:00 committed by Yusuke Tsutsumi
commit d063d44b73
6 changed files with 64 additions and 30 deletions

View file

@ -6,6 +6,7 @@ on:
env: env:
GCP_SERVICE_ACCOUNT: "github-ci@ansible-gcp-ci.iam.gserviceaccount.com" GCP_SERVICE_ACCOUNT: "github-ci@ansible-gcp-ci.iam.gserviceaccount.com"
GCP_PROJECT: "ansible-gcp-ci" GCP_PROJECT: "ansible-gcp-ci"
GCP_FOLDER_ID: "542027184392"
jobs: jobs:
integration: integration:
# NOTE: GitHub does not allow secrets to be used # NOTE: GitHub does not allow secrets to be used
@ -44,6 +45,7 @@ jobs:
gcp_cred_file: /tmp/service-account-key.json gcp_cred_file: /tmp/service-account-key.json
gcp_cred_kind: serviceaccount gcp_cred_kind: serviceaccount
gcp_cred_email: $GCP_SERVICE_ACCOUNT gcp_cred_email: $GCP_SERVICE_ACCOUNT
gcp_folder_id: $GCP_FOLDER_ID
" > ./tests/integration/cloud-config-gcp.ini " > ./tests/integration/cloud-config-gcp.ini
# cleanup test environment # cleanup test environment
- name: Auth to Gcloud - name: Auth to Gcloud
@ -58,7 +60,7 @@ jobs:
- name: Run cleanup - name: Run cleanup
run: | run: |
./scripts/bootstrap-project.sh $GCP_PROJECT $GCP_SERVICE_ACCOUNT ./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 # run tests
- name: Run integration tests - name: Run integration tests
# Add the -vvv flag to print out more output # Add the -vvv flag to print out more output

View file

@ -40,6 +40,7 @@ gcp_project: @PROJECT_ID
gcp_cred_file: @CRED_FILE gcp_cred_file: @CRED_FILE
gcp_cred_kind: @CRED_KIND gcp_cred_kind: @CRED_KIND
gcp_cred_email: @EMAIL gcp_cred_email: @EMAIL
gcp_folder_id: @TEST_FOLDER (to create test projects)
``` ```
#### Setting up the project for testing #### Setting up the project for testing
@ -97,5 +98,4 @@ the codebase.
### Updating the supported ansible-core version ### 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. 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).

View file

@ -203,6 +203,8 @@ id:
type: str type: str
''' '''
ACTIVE = "ACTIVE"
################################################################################ ################################################################################
# Imports # Imports
################################################################################ ################################################################################
@ -250,7 +252,7 @@ def main():
update(module, self_link(module)) update(module, self_link(module))
fetch = fetch_resource(module, self_link(module)) fetch = fetch_resource(module, self_link(module))
changed = True changed = True
else: elif fetch.get("lifecycleState") == ACTIVE:
delete(module, self_link(module)) delete(module, self_link(module))
fetch = {} fetch = {}
changed = True changed = True
@ -375,7 +377,7 @@ def async_op_url(module, extra_data=None):
def wait_for_operation(module, response): def wait_for_operation(module, response):
op_result = return_if_object(module, response) op_result = return_if_object(module, response)
if op_result is None: if not op_result:
return {} return {}
status = navigate_hash(op_result, ['done']) status = navigate_hash(op_result, ['done'])
wait_done = wait_for_completion(status, op_result, module) wait_done = wait_for_completion(status, op_result, module)

View file

@ -77,6 +77,11 @@ options:
- This should not be set unless you know what you're doing. - This should not be set unless you know what you're doing.
- This only alters the User Agent string for any API requests. - This only alters the User Agent string for any API requests.
type: str type: str
page_size:
description:
- Indicates the number of projects that should be returned by the API
request
type: str
notes: notes:
- for authentication, you can set service_account_file using the C(GCP_SERVICE_ACCOUNT_FILE) - for authentication, you can set service_account_file using the C(GCP_SERVICE_ACCOUNT_FILE)
env variable. env variable.
@ -96,6 +101,7 @@ EXAMPLES = '''
project: test_project project: test_project
auth_kind: serviceaccount auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem" service_account_file: "/tmp/auth.pem"
page_size: 100
''' '''
RETURN = ''' RETURN = '''
@ -175,7 +181,9 @@ import json
def main(): def main():
module = GcpModule(argument_spec=dict()) module = GcpModule(argument_spec=dict(
page_size=dict(type='int')
))
if not module.params['scopes']: if not module.params['scopes']:
module.params['scopes'] = ['https://www.googleapis.com/auth/cloud-platform'] module.params['scopes'] = ['https://www.googleapis.com/auth/cloud-platform']
@ -190,7 +198,10 @@ def collection(module):
def fetch_list(module, link): def fetch_list(module, link):
auth = GcpSession(module, 'resourcemanager') 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): def return_if_object(module, response):

View file

@ -8,6 +8,7 @@
# - google-cloud-sdk (gcloudgcloud ) # - google-cloud-sdk (gcloudgcloud )
set -e set -e
PROJECT_ID="${1}" PROJECT_ID="${1}"
FOLDER_ID="${2}"
# service account is unused today # service account is unused today
# SERVICE_ACCOUNT_NAME="${2}" # SERVICE_ACCOUNT_NAME="${2}"
ZONE="us-central1-a" ZONE="us-central1-a"
@ -28,6 +29,9 @@ main() {
cleanup_resource "compute" "backend-services" "--global" "--global" cleanup_resource "compute" "backend-services" "--global" "--global"
cleanup_resource "compute" "backend-services" \ cleanup_resource "compute" "backend-services" \
"--regions=us-central1" "--region=us-central1" "--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() { cleanup_resource() {
@ -35,9 +39,14 @@ cleanup_resource() {
resource="$2" resource="$2"
extra_list_arg="$3" extra_list_arg="$3"
extra_delete_arg="$4" 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 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}" 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 done
} }

View file

@ -15,52 +15,57 @@
# Pre-test setup # Pre-test setup
- name: delete a project - name: delete a project
google.cloud.gcp_resourcemanager_project: google.cloud.gcp_resourcemanager_project:
name: My Sample Project name: "{{ resource_prefix[0:30] }}"
id: ansible-test-{{ 10000000000 | random }} id: "{{ resource_prefix[0:30] }}"
auth_kind: "{{ gcp_cred_kind }}" auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}" service_account_file: "{{ gcp_cred_file }}"
parent: parent:
type: organization type: folder
id: 636173955921 id: "{{ gcp_folder_id }}"
state: absent state: absent
#---------------------------------------------------------- #----------------------------------------------------------
- name: create a project - name: create a project
google.cloud.gcp_resourcemanager_project: google.cloud.gcp_resourcemanager_project:
name: My Sample Project name: "{{ resource_prefix[0:30] }}"
id: ansible-test-{{ 10000000000 | random }} id: "{{ resource_prefix[0:30] }}"
auth_kind: "{{ gcp_cred_kind }}" auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}" service_account_file: "{{ gcp_cred_file }}"
parent: parent:
type: organization type: folder
id: 636173955921 id: "{{ gcp_folder_id }}"
state: present state: present
register: result register: result
- name: assert changed is true - name: assert changed is true
assert: assert:
that: that:
- result.changed == true - result.changed == true
- name: Pause for 2 minutes for project to appear
ansible.builtin.pause:
minutes: 2
- name: verify that project was created - name: verify that project was created
google.cloud.gcp_resourcemanager_project_info: google.cloud.gcp_resourcemanager_project_info:
project: "{{ gcp_project }}" project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}" auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}" service_account_file: "{{ gcp_cred_file }}"
# choose 1000 projects so iterate past the deleted ones.
page_size: 1000
scopes: scopes:
- https://www.googleapis.com/auth/cloud-platform - https://www.googleapis.com/auth/cloud-platform
register: results register: results
- name: verify that command succeeded - name: verify that command succeeded
assert: assert:
that: 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 - name: create a project that already exists
google.cloud.gcp_resourcemanager_project: google.cloud.gcp_resourcemanager_project:
name: My Sample Project name: "{{ resource_prefix[0:30] }}"
id: ansible-test-{{ 10000000000 | random }} id: "{{ resource_prefix[0:30] }}"
auth_kind: "{{ gcp_cred_kind }}" auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}" service_account_file: "{{ gcp_cred_file }}"
parent: parent:
type: organization type: folder
id: 636173955921 id: "{{ gcp_folder_id }}"
state: present state: present
register: result register: result
- name: assert changed is false - name: assert changed is false
@ -70,41 +75,46 @@
#---------------------------------------------------------- #----------------------------------------------------------
- name: delete a project - name: delete a project
google.cloud.gcp_resourcemanager_project: google.cloud.gcp_resourcemanager_project:
name: My Sample Project name: "{{ resource_prefix[0:30] }}"
id: ansible-test-{{ 10000000000 | random }} id: "{{ resource_prefix[0:30] }}"
auth_kind: "{{ gcp_cred_kind }}" auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}" service_account_file: "{{ gcp_cred_file }}"
parent: parent:
type: organization type: folder
id: 636173955921 id: "{{ gcp_folder_id }}"
state: absent state: absent
register: result register: result
- name: assert changed is true - name: assert changed is true
assert: assert:
that: that:
- result.changed == true - result.changed == true
- name: Pause for 2 minutes for project to appear
ansible.builtin.pause:
minutes: 2
- name: verify that project was deleted - name: verify that project was deleted
google.cloud.gcp_resourcemanager_project_info: google.cloud.gcp_resourcemanager_project_info:
project: "{{ gcp_project }}" project: "{{ resource_prefix[0:30] }}"
auth_kind: "{{ gcp_cred_kind }}" auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}" service_account_file: "{{ gcp_cred_file }}"
# choose 1000 projects so iterate past the deleted ones.
page_size: 1000
scopes: scopes:
- https://www.googleapis.com/auth/cloud-platform - https://www.googleapis.com/auth/cloud-platform
register: results register: results
- name: verify that command succeeded - name: verify that command succeeded
assert: assert:
that: 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 - name: delete a project that does not exist
google.cloud.gcp_resourcemanager_project: google.cloud.gcp_resourcemanager_project:
name: My Sample Project name: "{{ resource_prefix[0:30] }}"
id: ansible-test-{{ 10000000000 | random }} id: "{{ resource_prefix[0:30] }}"
auth_kind: "{{ gcp_cred_kind }}" auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}" service_account_file: "{{ gcp_cred_file }}"
parent: parent:
type: organization type: folder
id: 636173955921 id: "{{ gcp_folder_id }}"
state: absent state: absent
register: result register: result
- name: assert changed is false - name: assert changed is false