Release v0.45.0#771
Conversation
* Pass --yes to ansible-specdoc for CI and require >=0.0.20 * Require latest version of ansible-specdoc
* Add condition to upload XML int test reports on push only * Modify condition to upload XML int test reports on push only * Add logic to upload test results for manual runs on demand only * Restore success/failure instead of always (Copilot suggestion) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Set test_upload_report to choice type as it is unequivocal --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Removed v4beta notices from Maintenance Policy documentation * Address CoPilot feedback
….0 (#760) Bumps [crazy-max/ghaction-github-labeler](https://github.com/crazy-max/ghaction-github-labeler) from 5.3.0 to 6.0.0. - [Release notes](https://github.com/crazy-max/ghaction-github-labeler/releases) - [Commits](crazy-max/ghaction-github-labeler@24d110a...548a7c3) --- updated-dependencies: - dependency-name: crazy-max/ghaction-github-labeler dependency-version: 6.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Drop support for ScaleGrid databases * Fix lint issues * Fix documentation header
* Locks stuff * More entity types * Fix code scan alert * Refactor to fix typing * Fix lint * Doc update * fix lint
…mentation and examples (#752)
…n and module specification (#765)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 7 to 8. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](actions/download-artifact@v7...v8) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: '8' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Dawid <56120592+dawiddzhafarov@users.noreply.github.com>
* Add support for increased block storage volume limits (#757) * Add support for increased block storage volume limits * Rename function * Apply copilot suggestions * Point to correct python-sdk branch * Add reminder to point to the latest released version of python-sdk * Pin linode_api4 --------- Co-authored-by: Dawid <56120592+dawiddzhafarov@users.noreply.github.com>
) * build(deps): bump slackapi/slack-github-action from 2.1.1 to 3.0.1 Bumps [slackapi/slack-github-action](https://github.com/slackapi/slack-github-action) from 2.1.1 to 3.0.1. - [Release notes](https://github.com/slackapi/slack-github-action/releases) - [Commits](slackapi/slack-github-action@v2.1.1...v3.0.1) --- updated-dependencies: - dependency-name: slackapi/slack-github-action dependency-version: 3.0.1 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * Update .github/workflows/nightly-smoke-tests.yml * Update .github/workflows/integration-tests.yml * Update .github/workflows/release-notify-slack.yml * Update .github/workflows/integration-tests.yml --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Zhiwei Liang <121905282+zliang-akamai@users.noreply.github.com>
* TPT-4318: Add @linode/dx-sdets to CODEOWNERS * Correct CODEOWNERS
There was a problem hiding this comment.
Pull request overview
Release v0.45.0 updates the Linode Ansible collection with new lock-management modules, expanded instance device support/validation, TTL normalization for domain records, and associated docs/tests/tooling updates.
Changes:
- Add
lock,lock_info, andlock_listmodules with documentation and integration coverage. - Expand instance config device mapping to support up to 64 devices and enforce per-instance device limits.
- Normalize
domain_record.ttl_secto valid TTL values and document/test the behavior.
Reviewed changes
Copilot reviewed 46 out of 47 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/unit/module_utils/test_linode_helper.py | Add unit test for suffix generator |
| tests/integration/targets/lock_basic/tasks/main.yaml | New lock module integration test |
| tests/integration/targets/instance_volumes_limit/tasks/main.yaml | New volume/device-limit integration test |
| tests/integration/targets/domain_record/tasks/main.yaml | Add TTL rounding integration coverage |
| scripts/specdoc_generate.sh | Non-interactive specdoc generation |
| requirements.txt | Bump dependencies |
| plugins/modules/maintenance_policy_list.py | Remove beta flag/docs wording |
| plugins/modules/lock_list.py | New list module for locks |
| plugins/modules/lock_info.py | New info module for locks |
| plugins/modules/lock.py | New create/delete lock module |
| plugins/modules/instance.py | Device suffix expansion + limit enforcement |
| plugins/modules/domain_record.py | TTL normalization logic |
| plugins/modules/database_postgresql.py | Remove deprecated module |
| plugins/modules/database_mysql.py | Remove deprecated module |
| plugins/modules/account_settings.py | Remove deprecated/unused fields/notes |
| plugins/module_utils/linode_helper.py | Add generate_device_suffixes helper |
| plugins/module_utils/linode_database_shared.py | Remove old update-window spec |
| plugins/module_utils/doc_fragments/lock_list.py | Docs fragment for lock_list |
| plugins/module_utils/doc_fragments/lock_info.py | Docs fragment for lock_info |
| plugins/module_utils/doc_fragments/lock.py | Docs fragment for lock |
| plugins/module_utils/doc_fragments/instance_list.py | Add locks field to sample |
| plugins/module_utils/doc_fragments/instance.py | Add locks field to sample |
| plugins/module_utils/doc_fragments/database_postgresql.py | Adjust sample fields (standby) |
| plugins/module_utils/doc_fragments/database_mysql.py | Adjust sample fields (standby) |
| plugins/module_utils/doc_fragments/database_list.py | Adjust sample fields (standby) |
| docs/modules/maintenance_policy_list.md | Remove beta warning banner |
| docs/modules/lock_list.md | New lock_list docs |
| docs/modules/lock_info.md | New lock_info docs |
| docs/modules/lock.md | New lock docs |
| docs/modules/instance_list.md | Add locks field to sample |
| docs/modules/instance_info.md | Add locks field to sample |
| docs/modules/instance.md | Document expanded device keys |
| docs/modules/domain_record.md | Document TTL rounding behavior |
| docs/modules/database_postgresql_info.md | Adjust sample fields (standby) |
| docs/modules/database_postgresql.md | Remove deprecated docs page |
| docs/modules/database_mysql_info.md | Adjust sample fields (standby) |
| docs/modules/database_mysql.md | Remove deprecated docs page |
| docs/modules/database_list.md | Adjust sample fields (standby) |
| docs/modules/account_settings.md | Remove deprecated/unused fields/notes |
| README.md | Update module list (add locks, remove deprecated db) |
| Makefile | Non-interactive specdoc injection |
| CODEOWNERS | Add dx-sdets as codeowners |
| .github/workflows/release-notify-slack.yml | Update Slack action version |
| .github/workflows/nightly-smoke-tests.yml | Update Slack action version |
| .github/workflows/labeler.yml | Update labeler action pin |
| .github/workflows/integration-tests.yml | Optional report upload + action bumps |
| .github/PULL_REQUEST_TEMPLATE.md | Remove preview section |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| failed_when: | ||
| - invalid_create.changed == true | ||
| - '"Too many devices specified for this instance type." not in invalid_create.msg' |
There was a problem hiding this comment.
The expected-failure logic here is hard to reason about and doesn't explicitly assert that the task failed for the right reason. A more robust pattern is to set failed_when: false, then add an assert that invalid_create.failed is true and that invalid_create.msg contains the expected substring.
| module = InfoModule( | ||
| primary_result=InfoModuleResult( | ||
| field_name="lock", | ||
| field_type=FieldType.dict, | ||
| display_name="Lock", | ||
| samples=docs_parent.result_lock_samples, | ||
| ), |
There was a problem hiding this comment.
Most *_info modules set docs_url on the primary InfoModuleResult, but lock_info omits it. Adding the appropriate API reference URL will improve generated documentation consistency and ensure users can navigate to the canonical response schema.
| - name: List locks filtered by lock_type | ||
| linode.cloud.lock_list: | ||
| filters: | ||
| - name: lock_type | ||
| values: cannot_delete | ||
| register: list_locks_filtered |
There was a problem hiding this comment.
filters[*].values is passed into construct_api_filter which iterates it as a list. Using a scalar string here will be iterated character-by-character and produce an invalid filter. Set values to a YAML list (e.g., values: ['cannot_delete']).
| def _find_existing_lock(self) -> Optional[dict]: | ||
| """Find an existing lock for the given entity.""" | ||
| entity_type = self.module.params.get("entity_type") | ||
| entity_id = self.module.params.get("entity_id") | ||
| lock_type = self.module.params.get("lock_type") | ||
|
|
||
| try: | ||
| locks = self.client.locks() | ||
| for lock in locks: | ||
| if ( | ||
| lock.entity.type == entity_type | ||
| and lock.entity.id == entity_id | ||
| and lock.lock_type == lock_type | ||
| ): | ||
| return lock._raw_json |
There was a problem hiding this comment.
_find_existing_lock only treats a lock as existing if the lock_type matches. Because the API allows only one delete-protection lock per resource, requesting state=present with a different lock_type will attempt a create and likely fail. Consider detecting any existing lock for the entity and either (a) fail with a clear message instructing the user to delete/recreate, or (b) delete the existing lock and create the requested one (documenting that behavior).
| try: | ||
| lock = self.client.load(Lock, lock_id) | ||
| lock._api_get() | ||
| except Exception: | ||
| # Lock doesn't exist, nothing to do | ||
| return |
There was a problem hiding this comment.
_handle_absent catches all exceptions and treats them as "lock doesn't exist". This can mask real failures (auth errors, network errors, 5xx) and make the module appear idempotent when it actually failed. Catch ApiError and only ignore 404/not-found; re-raise or fail for other exceptions.
| result_field_name="locks", | ||
| endpoint_template="/locks", | ||
| result_docs_url="TBD", | ||
| examples=docs.specdoc_examples, | ||
| result_samples=docs.result_locks_samples, |
There was a problem hiding this comment.
result_docs_url is still set to "TBD". This flows into generated docs and makes the module documentation incomplete. Replace with the correct Linode API reference URL for listing locks before release.
| validate_required, | ||
| ) | ||
| from ansible_collections.linode.cloud.plugins.modules.instance import MAX_DEVICE_LIMIT | ||
|
|
There was a problem hiding this comment.
This unit test imports MAX_DEVICE_LIMIT from the instance module, which can couple the test suite to Ansible module import side effects and make the helper test harder to run in isolation. Consider asserting against a literal (e.g., 64) or moving the constant to module_utils alongside generate_device_suffixes and importing it from there.
| | Field | Type | Required | Description | | ||
| |-----------|------|----------|------------------------------------------------------------------------------| | ||
| | `name` | <center>`str`</center> | <center>**Required**</center> | The name of the field to filter on. Valid filterable fields can be found [here](TBD). | | ||
| | `values` | <center>`list`</center> | <center>**Required**</center> | A list of values to allow for this field. Fields will pass this filter if at least one of these values matches. | | ||
|
|
||
| ## Return Values | ||
|
|
||
| - `locks` - The returned Locks. | ||
|
|
||
| - Sample Response: | ||
| ```json | ||
| [ | ||
| { | ||
| "id": 1, | ||
| "lock_type": "cannot_delete_with_subresources", | ||
| "entity": { | ||
| "id": 290349, | ||
| "type": "linode", | ||
| "label": "linode290349", | ||
| "url": "/v4/linode/instances/290349" | ||
| } | ||
| } | ||
| ] | ||
| ``` | ||
| - See the [Linode API response documentation](TBD) for a list of returned fields |
There was a problem hiding this comment.
This doc page still contains "TBD" placeholders for the filterable-fields link and the API response documentation link. These should be replaced with the correct URLs so users can discover valid filters and response fields.
| def generate_device_suffixes(max_device_limit: int) -> List[str]: | ||
| """ | ||
| Generates a list of device suffixes. Currently supports up to 64 devices, | ||
| which is the maximum number of devices supported by Linode instances. | ||
| The suffixes are generated in the format of a, b, c, ..., z, aa, ab, ..., az, ba, bb, ..., bl. | ||
| """ | ||
| result = [] | ||
| for i in range(max_device_limit): | ||
| if i < 26: | ||
| result.append(chr(ord("a") + i)) | ||
| else: | ||
| shifted = i - 26 | ||
| first_letter = chr(ord("a") + (shifted // 26)) | ||
| second_letter = chr(ord("a") + (shifted % 26)) | ||
| result.append(first_letter + second_letter) |
There was a problem hiding this comment.
The docstring says this helper "supports up to 64 devices", but the function accepts any max_device_limit and will start generating non-[a-z] prefixes for sufficiently large values. Add input validation (e.g., clamp/raise when max_device_limit is out of the supported range) or update the docstring to reflect the actual supported range.
mgwoj
left a comment
There was a problem hiding this comment.
Can those TBD links be updated?
…se notes workflow (#773) * Added PR title checking to lint workflow and clean up release notes * Bumped actions/github-script from v7 to v8
…test issues blocking release (#774) * Use devices dict passthrough for config_create(...) BREAKING: Remove managed database backups per legacy backend EOL Correct instance_backup_enabled test * Update invalid label error assertions * Tidy up instance_backup_enabled test * Fix nodebalancer_udp integration test case * Fix test failures * Invalidate instance cache after disk updates
* Added support for setting disk_encryption upon LKE Node Pool creation * Fix lint
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6 to 7. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](actions/upload-artifact@v6...v7) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* doc and test * fix doc * update doc sample * update doc example
* docs: update API documentation links for resource locks * Update doc link from get to post endpoint * Fix
…port in-place config updates (#778) * Address nodebalancer module ordering and sync issues * make format * fix lint * Fix remaining issues * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * various fixes * oops * Fix UDP issue * Add support for in-place update logic * Fix regression * Address copilot feedback --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
No description provided.