fix linting and updating maintenance guide

Updating the maintainers guide with updated intructions from
Ansible engineers.

Fixing linting issues, and adding the linter as a GitHub workflow
to ensure there are no regressions.
This commit is contained in:
Yusuke Tsutsumi 2022-12-06 22:06:02 -08:00 committed by Yusuke Tsutsumi
commit a9545c77a4
15 changed files with 91 additions and 74 deletions

View file

@ -1,34 +1,35 @@
name: "Run tests for the cloud.google collection" name: "Run tests for the cloud.google collection"
on: [pull_request] on: [pull_request]
env:
PYTHON_VERSION: "3.9" # minimum version for Ansible 2.14
jobs: jobs:
# sanity tests cannot be turned on until #498 is resolved. sanity:
# sanity: runs-on: ubuntu-latest
# runs-on: ubuntu-latest defaults:
# defaults: run:
# run: working-directory: ansible_collections/google/cloud
# working-directory: ansible_collections/google/cloud strategy:
# strategy: matrix:
# matrix: ansible_version:
# ansible_version: - stable-2.14
# - stable-2.13 steps:
# - stable-2.11 - name: check out code
# steps: uses: actions/checkout@v2
# - name: check out code with:
# uses: actions/checkout@v2 path: ansible_collections/google/cloud
# with: - name: Set up Python
# path: ansible_collections/google/cloud uses: actions/setup-python@v1
# - name: Set up Python with:
# uses: actions/setup-python@v1 python-version: ${{ env.PYTHON_VERSION }}
# with: - name: Install ansible-base (${{ matrix.ansible_version }})
# python-version: '3.8' # this is the minimum version required for Ansible 2.11 uses: nick-invision/retry@v2
# - name: Install ansible-base (${{ matrix.ansible_version }}) with:
# uses: nick-invision/retry@v2 timeout_minutes: 3
# with: max_attempts: 3
# timeout_minutes: 3 command: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible_version }}.tar.gz --disable-pip-version-check
# max_attempts: 3 - name: Run sanity tests
# command: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible_version }}.tar.gz --disable-pip-version-check # validate-modules cannot be turned on until #498 is resolved.
# - name: Run sanity tests run: ansible-test sanity -v --color --python "$PYTHON_VERSION" --skip validate-modules
# run: ansible-test sanity --docker -v --color --python 3.8
unit: unit:
runs-on: ubuntu-latest runs-on: ubuntu-latest
defaults: defaults:
@ -47,7 +48,7 @@ jobs:
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v1 uses: actions/setup-python@v1
with: with:
python-version: '3.9' # this is the minimum version required for Ansible 2.14 python-version: ${{ env.PYTHON_VERSION }}
- name: Install dependencies - name: Install dependencies
run: pip install -r requirements.txt run: pip install -r requirements.txt
- name: Install test dependencies - name: Install test dependencies
@ -55,4 +56,4 @@ jobs:
- name: Install ansible-base (${{ matrix.ansible_version }}) - name: Install ansible-base (${{ matrix.ansible_version }})
run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible_version }}.tar.gz --disable-pip-version-check run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible_version }}.tar.gz --disable-pip-version-check
- name: Run unit tests - name: Run unit tests
run: ansible-test units -v --color --python 3.9 run: ansible-test units -v --color --python "$PYTHON_VERSION"

1
.gitignore vendored
View file

@ -4,3 +4,4 @@ tests/integration/cloud-config-gcp.ini
tests/integration/inventory tests/integration/inventory
tests/output/ tests/output/
__pycache__ __pycache__
*.tar.gz

View file

@ -58,11 +58,23 @@ antsibull-changelog release
This will remove all the changelog fragments from ./changelogs/fragments and This will remove all the changelog fragments from ./changelogs/fragments and
merge them into CHANGELOG.rst. merge them into CHANGELOG.rst.
### Tag a release ### Create a new GitHub release
The release process is mostly automated, relying on GitHub releases and the following Creating
workflows:
- [publish to Ansible Galaxy](./.github/workflows/pythonpublish.yml). - [publish to Ansible Galaxy](./.github/workflows/pythonpublish.yml).
- [publish to Automation Hub](./.github/workflows/automationhub.yml).
### Publish to Automation Hub
*note*: As automation Hub only accepts production releases, this step
is only required for new full releases.
This step does not use GitHub actions, as API keys for Automation Hub
expire after 30 days of no use, and a maintainer may find themselves
refreshing tokens every time anyway.
Steps:
1. Build the package locally: `ansible-galaxy collection build .`
1. [Go to the Automation Hub my-namespaces page, then click on Google](https://console.redhat.com/ansible/automation-hub/repo/published/my-namespaces/google/)
1. Publish the package

View file

@ -521,7 +521,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
return self._return_if_object(module, response) return self._return_if_object(module, response)
def projects_for_folder(self, config_data, folder): def projects_for_folder(self, config_data, folder):
link = 'https://cloudresourcemanager.googleapis.com/v1/projects'.format() link = 'https://cloudresourcemanager.googleapis.com/v1/projects'
query = 'parent.id = {0}'.format(folder) query = 'parent.id = {0}'.format(folder)
projects = [] projects = []
config_data['scopes'] = ['https://www.googleapis.com/auth/cloud-platform'] config_data['scopes'] = ['https://www.googleapis.com/auth/cloud-platform']

View file

@ -1433,7 +1433,7 @@ def main():
elements="dict", elements="dict",
options=dict( options=dict(
balancing_mode=dict(default="UTILIZATION", type="str"), balancing_mode=dict(default="UTILIZATION", type="str"),
# TODO: capacity_scaler does some value normalization # TODO: capacity_scaler does some value normalization
# server-side, so there needs to be a way to do proper # server-side, so there needs to be a way to do proper
# value comparison. # value comparison.
capacity_scaler=dict(default="1", type="str"), capacity_scaler=dict(default="1", type="str"),

View file

@ -961,7 +961,7 @@ options:
paths: paths:
description: description:
- 'The list of path patterns to match. Each must start with / and the - 'The list of path patterns to match. Each must start with / and the
only place a \* is allowed is at the end following a /. The string fed only place a \\ * is allowed is at the end following a /. The string fed
to the path matcher does not include any text after the first ? or #, to the path matcher does not include any text after the first ? or #,
and those chars are not allowed here.' and those chars are not allowed here.'
elements: str elements: str
@ -2522,7 +2522,7 @@ pathMatchers:
paths: paths:
description: description:
- 'The list of path patterns to match. Each must start with / and the only - 'The list of path patterns to match. Each must start with / and the only
place a \* is allowed is at the end following a /. The string fed to the place a \\* is allowed is at the end following a /. The string fed to the
path matcher does not include any text after the first ? or #, and those path matcher does not include any text after the first ? or #, and those
chars are not allowed here.' chars are not allowed here.'
returned: success returned: success

View file

@ -991,7 +991,7 @@ resources:
paths: paths:
description: description:
- 'The list of path patterns to match. Each must start with / and the - 'The list of path patterns to match. Each must start with / and the
only place a \* is allowed is at the end following a /. The string only place a \\* is allowed is at the end following a /. The string
fed to the path matcher does not include any text after the first fed to the path matcher does not include any text after the first
? or #, and those chars are not allowed here.' ? or #, and those chars are not allowed here.'
returned: success returned: success

View file

@ -325,7 +325,7 @@ options:
paths: paths:
description: description:
- 'The list of path patterns to match. Each must start with / and the - 'The list of path patterns to match. Each must start with / and the
only place a \* is allowed is at the end following a /. The string fed only place a \\* is allowed is at the end following a /. The string fed
to the path matcher does not include any text after the first ? or #, to the path matcher does not include any text after the first ? or #,
and those chars are not allowed here.' and those chars are not allowed here.'
elements: str elements: str
@ -2899,7 +2899,7 @@ pathMatchers:
paths: paths:
description: description:
- 'The list of path patterns to match. Each must start with / and the only - 'The list of path patterns to match. Each must start with / and the only
place a \* is allowed is at the end following a /. The string fed to the place a \\* is allowed is at the end following a /. The string fed to the
path matcher does not include any text after the first ? or #, and those path matcher does not include any text after the first ? or #, and those
chars are not allowed here.' chars are not allowed here.'
returned: success returned: success
@ -5489,10 +5489,10 @@ def main():
if fetch: if fetch:
module.params['fingerprint'] = fetch['fingerprint'] module.params['fingerprint'] = fetch['fingerprint']
if state == 'present': if state == 'present':
if is_different(module, fetch): if is_different(module, fetch):
update(module, self_link(module), kind) update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind) fetch = fetch_resource(module, self_link(module), kind)
changed = True changed = True
else: else:
delete(module, self_link(module), kind) delete(module, self_link(module), kind)
fetch = {} fetch = {}

View file

@ -382,7 +382,7 @@ resources:
paths: paths:
description: description:
- 'The list of path patterns to match. Each must start with / and the - 'The list of path patterns to match. Each must start with / and the
only place a \* is allowed is at the end following a /. The string only place a \\* is allowed is at the end following a /. The string
fed to the path matcher does not include any text after the first fed to the path matcher does not include any text after the first
? or #, and those chars are not allowed here.' ? or #, and those chars are not allowed here.'
returned: success returned: success

View file

@ -535,14 +535,14 @@ def is_different(module, response):
response_vals = {} response_vals = {}
for k, v in response.items(): for k, v in response.items():
if k in keys_to_ignore: if k in keys_to_ignore:
continue continue
if k in request: if k in request:
response_vals[k] = v response_vals[k] = v
request_vals = {} request_vals = {}
for k, v in request.items(): for k, v in request.items():
if k in keys_to_ignore: if k in keys_to_ignore:
continue continue
if k in response: if k in response:
request_vals[k] = v request_vals[k] = v

View file

@ -219,9 +219,9 @@ def main():
fetch = fetch_resource(module, self_link(module)) fetch = fetch_resource(module, self_link(module))
changed = True changed = True
elif not fetch.get("deleted"): elif not fetch.get("deleted"):
delete(module, self_link(module)) delete(module, self_link(module))
fetch = {} fetch = {}
changed = True changed = True
else: else:
if state == "present": if state == "present":
fetch = create(module, collection(module)) fetch = create(module, collection(module))
@ -242,7 +242,7 @@ def create(module, link):
def undelete(module, link, etag): def undelete(module, link, etag):
auth = GcpSession(module, "iam") auth = GcpSession(module, "iam")
return return_if_object(module, auth.post(link + ":undelete", { return return_if_object(module, auth.post(link + ":undelete", {
"etag": etag "etag": etag
})) }))
@ -322,8 +322,8 @@ def return_if_object(module, response, allow_not_found=False):
# catches and edge case specific to IAM roles where the role not # catches and edge case specific to IAM roles where the role not
# existing returns 400. # existing returns 400.
if (allow_not_found and response.status_code == 400 if (allow_not_found and response.status_code == 400
and "You can't delete role_id" in response.text): and "You can't delete role_id" in response.text):
return None return None
try: try:

@ -1 +0,0 @@
Subproject commit 9a36582f0d762e386a56e698d896c22bebf6d904

View file

@ -8,42 +8,45 @@
# - google-cloud-sdk (gcloudgcloud ) # - google-cloud-sdk (gcloudgcloud )
set -e set -e
PROJECT_ID="${1}" PROJECT_ID="${1}"
SERVICE_ACCOUNT_NAME="${2}" # service account is unused today
# SERVICE_ACCOUNT_NAME="${2}"
ZONE="us-central1-a" ZONE="us-central1-a"
main() { main() {
# note: the ordering here is deliberate, to start with # note: the ordering here is deliberate, to start with
# leaf resources and work upwards to parent resources. # leaf resources and work upwards to parent resources.
cleanup_resource_per_region "compute vpn-tunnels" cleanup_resource_per_region "compute" "vpn-tunnels"
cleanup_resource "compute instances" "" "--zone=$ZONE" cleanup_resource "compute" "instances" "" "--zone=$ZONE"
cleanup_resource_per_region "compute addresses" cleanup_resource_per_region "compute" "addresses"
cleanup_resource "compute target-http-proxies" "" "--global" cleanup_resource "compute" "target-http-proxies" "" "--global"
cleanup_resource "compute forwarding-rules" "--global" "--global" cleanup_resource "compute" "forwarding-rules" "--global" "--global"
cleanup_resource "compute forwarding-rules" \ cleanup_resource "compute" "forwarding-rules" \
"--regions=us-central1" "--region=us-central1" "--regions=us-central1" "--region=us-central1"
cleanup_resource "compute url-maps" "--global" "--global" cleanup_resource "compute" "url-maps" "--global" "--global"
cleanup_resource "compute url-maps" \ cleanup_resource "compute" "url-maps" \
"--regions=us-central1" "--region=us-central1" "--regions=us-central1" "--region=us-central1"
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"
} }
cleanup_resource() { cleanup_resource() {
resource_group="$1" resource_group="$1"
extra_list_args="$2" resource="$2"
extra_delete_args="$3" extra_list_arg="$3"
extra_delete_arg="$4"
for resource in $(gcloud $resource_group list --project="${PROJECT_ID}" --format="csv[no-heading](name)" $extra_list_args); 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 delete "${resource}" --project="${PROJECT_ID}" -q $extra_delete_args gcloud "${resource_group}" "${resource}" delete "${resource_id}" --project="${PROJECT_ID}" -q "${extra_delete_arg}"
done done
} }
cleanup_resource_per_region() { cleanup_resource_per_region() {
resource_group="$1" resource_group="$1"
for resource_and_region in $(gcloud $resource_group list --project="${PROJECT_ID}" --format="csv[no-heading](name,region)"); do resource="$2"
read -r resource region < <(echo "$resource_and_region" | tr "," " ") for resource_and_region in $(gcloud "${resource_group}" "${resource}" list --project="${PROJECT_ID}" --format="csv[no-heading](name,region)"); do
gcloud $resource_group delete "${resource}" --project="${PROJECT_ID}" -q --region="${region}" read -r resource_id region < <(echo "$resource_and_region" | tr "," " ")
gcloud "${resource_group}" "${resource}" delete "${resource_id}" --project="${PROJECT_ID}" -q --region="${region}"
done done
} }

View file

@ -4,4 +4,4 @@
if [ -f ../cloud-function.zip ]; then if [ -f ../cloud-function.zip ]; then
rm ../cloud-function.zip rm ../cloud-function.zip
fi fi
zip ../cloud-function.zip * zip ../cloud-function.zip ./*

View file

@ -1,5 +1,6 @@
import functions_framework import functions_framework
# Register an HTTP function with the Functions Framework # Register an HTTP function with the Functions Framework
@functions_framework.http @functions_framework.http
def helloGET(request): def helloGET(request):