diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-18 05:52:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-18 05:52:22 +0000 |
commit | 38b7c80217c4e72b1d8988eb1e60bb6e77334114 (patch) | |
tree | 356e9fd3762877d07cde52d21e77070aeff7e789 /ansible_collections/community/hrobot | |
parent | Adding upstream version 7.7.0+dfsg. (diff) | |
download | ansible-38b7c80217c4e72b1d8988eb1e60bb6e77334114.tar.xz ansible-38b7c80217c4e72b1d8988eb1e60bb6e77334114.zip |
Adding upstream version 9.4.0+dfsg.upstream/9.4.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/community/hrobot')
36 files changed, 994 insertions, 276 deletions
diff --git a/ansible_collections/community/hrobot/.github/workflows/ansible-test.yml b/ansible_collections/community/hrobot/.github/workflows/ansible-test.yml index 10a685f4c..1e66b7d29 100644 --- a/ansible_collections/community/hrobot/.github/workflows/ansible-test.yml +++ b/ansible_collections/community/hrobot/.github/workflows/ansible-test.yml @@ -32,6 +32,8 @@ jobs: - stable-2.12 - stable-2.13 - stable-2.14 + - stable-2.15 + - stable-2.16 - devel # Ansible-test on various stable branches does not yet work well with cgroups v2. # Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04 @@ -71,6 +73,8 @@ jobs: - stable-2.12 - stable-2.13 - stable-2.14 + - stable-2.15 + - stable-2.16 - devel steps: diff --git a/ansible_collections/community/hrobot/.github/workflows/ee.yml b/ansible_collections/community/hrobot/.github/workflows/ee.yml index 04787e8ed..c4e751a79 100644 --- a/ansible_collections/community/hrobot/.github/workflows/ee.yml +++ b/ansible_collections/community/hrobot/.github/workflows/ee.yml @@ -22,25 +22,73 @@ env: jobs: build: - name: Build and test EE (Ⓐ${{ matrix.runner_tag }}) + name: Build and test EE (${{ matrix.name }}) strategy: + fail-fast: false matrix: - runner_tag: - - devel - - stable-2.12-latest - - stable-2.11-latest - - stable-2.9-latest + name: + - '' + ansible_core: + - '' + ansible_runner: + - '' + base_image: + - '' + pre_base: + - '' + extra_vars: + - '' + other_deps: + - '' + exclude: + - ansible_core: '' + include: + - name: ansible-core devel @ RHEL UBI 9 + ansible_core: https://github.com/ansible/ansible/archive/devel.tar.gz + ansible_runner: ansible-runner + other_deps: |2 + python_interpreter: + package_system: python3.11 python3.11-pip python3.11-wheel python3.11-cryptography + python_path: "/usr/bin/python3.11" + base_image: docker.io/redhat/ubi9:latest + pre_base: '"#"' + - name: ansible-core 2.15 @ Rocky Linux 9 + ansible_core: https://github.com/ansible/ansible/archive/stable-2.15.tar.gz + ansible_runner: ansible-runner + base_image: quay.io/rockylinux/rockylinux:9 + pre_base: '"#"' + - name: ansible-core 2.14 @ CentOS Stream 9 + ansible_core: https://github.com/ansible/ansible/archive/stable-2.14.tar.gz + ansible_runner: ansible-runner + base_image: quay.io/centos/centos:stream9 + pre_base: '"#"' + - name: ansible-core 2.13 @ RHEL UBI 8 + ansible_core: https://github.com/ansible/ansible/archive/stable-2.13.tar.gz + ansible_runner: ansible-runner + other_deps: |2 + python_interpreter: + package_system: python39 python39-pip python39-wheel python39-cryptography + base_image: docker.io/redhat/ubi8:latest + pre_base: '"#"' + - name: ansible-core 2.12 @ CentOS Stream 8 + ansible_core: https://github.com/ansible/ansible/archive/stable-2.12.tar.gz + ansible_runner: ansible-runner + other_deps: |2 + python_interpreter: + package_system: python39 python39-pip python39-wheel python39-cryptography + base_image: quay.io/centos/centos:stream8 + pre_base: '"#"' runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }} - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: - python-version: '3.10' + python-version: '3.11' - name: Install ansible-builder and ansible-navigator run: pip install ansible-builder ansible-navigator @@ -74,11 +122,26 @@ jobs: # EE config cat > execution-environment.yml <<EOF --- - version: 1 - build_arg_defaults: - EE_BASE_IMAGE: 'quay.io/ansible/ansible-runner:${{ matrix.runner_tag }}' + version: 3 dependencies: + ansible_core: + package_pip: ${{ matrix.ansible_core }} + ansible_runner: + package_pip: ${{ matrix.ansible_runner }} galaxy: requirements.yml + ${{ matrix.other_deps }} + + images: + base_image: + name: ${{ matrix.base_image }} + + additional_build_files: + - src: ${COLLECTION_FILENAME} + dest: src + + additional_build_steps: + prepend_base: + - ${{ matrix.pre_base }} EOF echo "::group::execution-environment.yml" cat execution-environment.yml @@ -88,26 +151,29 @@ jobs: cat > requirements.yml <<EOF --- collections: - - name: ${COLLECTION_FILENAME} + - name: src/${COLLECTION_FILENAME} type: file EOF echo "::group::requirements.yml" cat requirements.yml echo "::endgroup::" - - name: Build image based on ${{ matrix.runner_tag }} + - name: Build image based on ${{ matrix.base_image }} run: | - mkdir -p context/_build/ - cp "${{ env.NAMESPACE }}-${{ env.COLLECTION_NAME }}"-*.tar.gz context/_build/ - ansible-builder build -v 3 -t test-ee:latest --container-runtime=podman + ansible-builder build --verbosity 3 --tag test-ee:latest --container-runtime docker + + - name: Show images + run: docker image ls - name: Run basic tests run: > ansible-navigator run --mode stdout + --container-engine docker --pull-policy never --set-environment-variable ANSIBLE_PRIVATE_ROLE_VARS=true --execution-environment-image test-ee:latest -v all.yml + ${{ matrix.extra_vars }} working-directory: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }}/tests/ee diff --git a/ansible_collections/community/hrobot/.github/workflows/extra-tests.yml b/ansible_collections/community/hrobot/.github/workflows/extra-tests.yml index e00d93822..ee8964c3f 100644 --- a/ansible_collections/community/hrobot/.github/workflows/extra-tests.yml +++ b/ansible_collections/community/hrobot/.github/workflows/extra-tests.yml @@ -26,14 +26,14 @@ jobs: steps: - name: Check out code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: - python-version: '3.10' + python-version: '3.11' - name: Install ansible-core run: pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check diff --git a/ansible_collections/community/hrobot/.github/workflows/import-galaxy.yml b/ansible_collections/community/hrobot/.github/workflows/import-galaxy.yml index 8a5d43177..0c0ee402a 100644 --- a/ansible_collections/community/hrobot/.github/workflows/import-galaxy.yml +++ b/ansible_collections/community/hrobot/.github/workflows/import-galaxy.yml @@ -4,7 +4,7 @@ # SPDX-License-Identifier: GPL-3.0-or-later name: import-galaxy -on: +'on': # Run CI against all pushes (direct commits, also merged PRs) to main, and all Pull Requests push: branches: @@ -12,77 +12,9 @@ on: - stable-* pull_request: -env: - # Adjust this to your collection - NAMESPACE: community - COLLECTION_NAME: hrobot - jobs: - build-collection: - name: Build collection artifact - runs-on: ubuntu-latest - steps: - - name: Check out code - uses: actions/checkout@v3 - with: - path: ./checkout - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: '3.10' - - - name: Install ansible-core - run: pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check - - - name: Make sure galaxy.yml has version entry - run: >- - python -c - 'import yaml ; - f = open("galaxy.yml", "rb") ; - data = yaml.safe_load(f) ; - f.close() ; - data["version"] = data.get("version") or "0.0.1" ; - f = open("galaxy.yml", "wb") ; - f.write(yaml.dump(data).encode("utf-8")) ; - f.close() ; - ' - working-directory: ./checkout - - - name: Build collection - run: ansible-galaxy collection build - working-directory: ./checkout - - - name: Copy artifact into subdirectory - run: mkdir ./artifact && mv ./checkout/${{ env.NAMESPACE }}-${{ env.COLLECTION_NAME }}-*.tar.gz ./artifact - - - name: Upload artifact - uses: actions/upload-artifact@v3 - with: - name: ${{ env.NAMESPACE }}-${{ env.COLLECTION_NAME }}-${{ github.sha }} - path: ./artifact/ - import-galaxy: - name: Import artifact with Galaxy importer - runs-on: ubuntu-latest - needs: - - build-collection - steps: - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: '3.10' - - - name: Install ansible-core - run: pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check - - - name: Install galaxy-importer - run: pip install galaxy-importer --disable-pip-version-check - - - name: Download artifact - uses: actions/download-artifact@v3 - with: - name: ${{ env.NAMESPACE }}-${{ env.COLLECTION_NAME }}-${{ github.sha }} - - - name: Run Galaxy importer - run: python -m galaxy_importer.main ${{ env.NAMESPACE }}-${{ env.COLLECTION_NAME }}-*.tar.gz + permissions: + contents: read + name: Test to import built collection artifact with Galaxy importer + uses: ansible-community/github-action-test-galaxy-import/.github/workflows/test-galaxy-import.yml@main diff --git a/ansible_collections/community/hrobot/.github/workflows/reuse.yml b/ansible_collections/community/hrobot/.github/workflows/reuse.yml index 06a3fa455..51d9ac2fb 100644 --- a/ansible_collections/community/hrobot/.github/workflows/reuse.yml +++ b/ansible_collections/community/hrobot/.github/workflows/reuse.yml @@ -21,12 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - name: Install dependencies - run: | - pip install reuse - - - name: Check REUSE compliance - run: | - reuse lint + - name: REUSE Compliance Check + uses: fsfe/reuse-action@v3 diff --git a/ansible_collections/community/hrobot/CHANGELOG.md b/ansible_collections/community/hrobot/CHANGELOG.md new file mode 100644 index 000000000..d09d85be0 --- /dev/null +++ b/ansible_collections/community/hrobot/CHANGELOG.md @@ -0,0 +1,358 @@ +# Community Hetzner Robot Collection Release Notes + +**Topics** + +- <a href="#v1-9-1">v1\.9\.1</a> + - <a href="#release-summary">Release Summary</a> + - <a href="#security-fixes">Security Fixes</a> +- <a href="#v1-9-0">v1\.9\.0</a> + - <a href="#release-summary-1">Release Summary</a> + - <a href="#minor-changes">Minor Changes</a> + - <a href="#deprecated-features">Deprecated Features</a> +- <a href="#v1-8-2">v1\.8\.2</a> + - <a href="#release-summary-2">Release Summary</a> + - <a href="#bugfixes">Bugfixes</a> +- <a href="#v1-8-1">v1\.8\.1</a> + - <a href="#release-summary-3">Release Summary</a> + - <a href="#known-issues">Known Issues</a> +- <a href="#v1-8-0">v1\.8\.0</a> + - <a href="#release-summary-4">Release Summary</a> + - <a href="#major-changes">Major Changes</a> + - <a href="#minor-changes-1">Minor Changes</a> +- <a href="#v1-7-0">v1\.7\.0</a> + - <a href="#release-summary-5">Release Summary</a> + - <a href="#new-modules">New Modules</a> +- <a href="#v1-6-0">v1\.6\.0</a> + - <a href="#release-summary-6">Release Summary</a> + - <a href="#minor-changes-2">Minor Changes</a> +- <a href="#v1-5-2">v1\.5\.2</a> + - <a href="#release-summary-7">Release Summary</a> + - <a href="#minor-changes-3">Minor Changes</a> +- <a href="#v1-5-1">v1\.5\.1</a> + - <a href="#release-summary-8">Release Summary</a> +- <a href="#v1-5-0">v1\.5\.0</a> + - <a href="#release-summary-9">Release Summary</a> + - <a href="#minor-changes-4">Minor Changes</a> +- <a href="#v1-4-0">v1\.4\.0</a> + - <a href="#release-summary-10">Release Summary</a> + - <a href="#minor-changes-5">Minor Changes</a> +- <a href="#v1-3-1">v1\.3\.1</a> + - <a href="#release-summary-11">Release Summary</a> + - <a href="#bugfixes-1">Bugfixes</a> +- <a href="#v1-3-0">v1\.3\.0</a> + - <a href="#release-summary-12">Release Summary</a> + - <a href="#minor-changes-6">Minor Changes</a> + - <a href="#bugfixes-2">Bugfixes</a> +- <a href="#v1-2-3">v1\.2\.3</a> + - <a href="#release-summary-13">Release Summary</a> +- <a href="#v1-2-2">v1\.2\.2</a> + - <a href="#release-summary-14">Release Summary</a> + - <a href="#bugfixes-3">Bugfixes</a> +- <a href="#v1-2-1">v1\.2\.1</a> + - <a href="#release-summary-15">Release Summary</a> + - <a href="#minor-changes-7">Minor Changes</a> +- <a href="#v1-2-0">v1\.2\.0</a> + - <a href="#release-summary-16">Release Summary</a> + - <a href="#minor-changes-8">Minor Changes</a> + - <a href="#new-modules-1">New Modules</a> +- <a href="#v1-1-1">v1\.1\.1</a> + - <a href="#release-summary-17">Release Summary</a> + - <a href="#bugfixes-4">Bugfixes</a> +- <a href="#v1-1-0">v1\.1\.0</a> + - <a href="#release-summary-18">Release Summary</a> + - <a href="#new-plugins">New Plugins</a> + - <a href="#inventory">Inventory</a> +- <a href="#v1-0-0">v1\.0\.0</a> + - <a href="#release-summary-19">Release Summary</a> + - <a href="#breaking-changes--porting-guide">Breaking Changes / Porting Guide</a> + +<a id="v1-9-1"></a> +## v1\.9\.1 + +<a id="release-summary"></a> +### Release Summary + +Bugfix release\. + +<a id="security-fixes"></a> +### Security Fixes + +* robot inventory plugin \- make sure all data received from the Hetzner robot service server is marked as unsafe\, so remote code execution by obtaining texts that can be evaluated as templates is not possible \([https\://www\.die\-welt\.net/2024/03/remote\-code\-execution\-in\-ansible\-dynamic\-inventory\-plugins/](https\://www\.die\-welt\.net/2024/03/remote\-code\-execution\-in\-ansible\-dynamic\-inventory\-plugins/)\, [https\://github\.com/ansible\-collections/community\.hrobot/pull/99](https\://github\.com/ansible\-collections/community\.hrobot/pull/99)\)\. + +<a id="v1-9-0"></a> +## v1\.9\.0 + +<a id="release-summary-1"></a> +### Release Summary + +Feature and maintenance release\. + +<a id="minor-changes"></a> +### Minor Changes + +* robot inventory plugin \- the <code>filters</code> option has been renamed to <code>simple\_filters</code>\. The old name still works until community\.hrobot 2\.0\.0\. Then it will change to allow more complex filtering with the <code>community\.library\_inventory\_filtering\_v1</code> collection\'s functionality \([https\://github\.com/ansible\-collections/community\.hrobot/pull/94](https\://github\.com/ansible\-collections/community\.hrobot/pull/94)\)\. + +<a id="deprecated-features"></a> +### Deprecated Features + +* robot inventory plugin \- the <code>filters</code> option has been renamed to <code>simple\_filters</code>\. The old name will stop working in community\.hrobot 2\.0\.0 \([https\://github\.com/ansible\-collections/community\.hrobot/pull/94](https\://github\.com/ansible\-collections/community\.hrobot/pull/94)\)\. + +<a id="v1-8-2"></a> +## v1\.8\.2 + +<a id="release-summary-2"></a> +### Release Summary + +Maintenance release with updated documentation\. + +<a id="bugfixes"></a> +### Bugfixes + +* Show more information \(if available\) from error messages \([https\://github\.com/ansible\-collections/community\.hrobot/pull/89](https\://github\.com/ansible\-collections/community\.hrobot/pull/89)\)\. + +<a id="v1-8-1"></a> +## v1\.8\.1 + +<a id="release-summary-3"></a> +### Release Summary + +Maintenance release with updated documentation\. + +From this version on\, community\.hrobot is using the new [Ansible semantic markup](https\://docs\.ansible\.com/ansible/devel/dev\_guide/developing\_modules\_documenting\.html\#semantic\-markup\-within\-module\-documentation) +in its documentation\. If you look at documentation with the ansible\-doc CLI tool +from ansible\-core before 2\.15\, please note that it does not render the markup +correctly\. You should be still able to read it in most cases\, but you need +ansible\-core 2\.15 or later to see it as it is intended\. Alternatively you can +look at [the devel docsite](https\://docs\.ansible\.com/ansible/devel/collections/community/hrobot/) +for the rendered HTML version of the documentation of the latest release\. + +<a id="known-issues"></a> +### Known Issues + +* Ansible markup will show up in raw form on ansible\-doc text output for ansible\-core before 2\.15\. If you have trouble deciphering the documentation markup\, please upgrade to ansible\-core 2\.15 \(or newer\)\, or read the HTML documentation on [https\://docs\.ansible\.com/ansible/devel/collections/community/hrobot/](https\://docs\.ansible\.com/ansible/devel/collections/community/hrobot/)\. + +<a id="v1-8-0"></a> +## v1\.8\.0 + +<a id="release-summary-4"></a> +### Release Summary + +Feature release for the Hetzner firewall changes\. + +<a id="major-changes"></a> +### Major Changes + +* firewall \- Hetzner added output rules support to the firewall\. This change unfortunately means that using old versions of the firewall module will always set the output rule list to empty\, thus disallowing the server to send out packets \([https\://github\.com/ansible\-collections/community\.hrobot/issues/75](https\://github\.com/ansible\-collections/community\.hrobot/issues/75)\, [https\://github\.com/ansible\-collections/community\.hrobot/pull/76](https\://github\.com/ansible\-collections/community\.hrobot/pull/76)\)\. + +<a id="minor-changes-1"></a> +### Minor Changes + +* firewall\, firewall\_info \- add <code>filter\_ipv6</code> and <code>rules\.output</code> output to support the new IPv6 filtering and output rules features \([https\://github\.com/ansible\-collections/community\.hrobot/issues/75](https\://github\.com/ansible\-collections/community\.hrobot/issues/75)\, [https\://github\.com/ansible\-collections/community\.hrobot/pull/76](https\://github\.com/ansible\-collections/community\.hrobot/pull/76)\)\. +* firewall\, firewall\_info \- add <code>server\_number</code> option that can be used instead of <code>server\_ip</code> to identify the server\. Hetzner deprecated configuring the firewall by <code>server\_ip</code>\, so using <code>server\_ip</code> will stop at some point in the future \([https\://github\.com/ansible\-collections/community\.hrobot/pull/77](https\://github\.com/ansible\-collections/community\.hrobot/pull/77)\)\. + +<a id="v1-7-0"></a> +## v1\.7\.0 + +<a id="release-summary-5"></a> +### Release Summary + +Feature release\. + +<a id="new-modules"></a> +### New Modules + +* community\.hrobot\.v\_switch \- Manage Hetzner\'s vSwitch + +<a id="v1-6-0"></a> +## v1\.6\.0 + +<a id="release-summary-6"></a> +### Release Summary + +Feature release with improved documentation\. + +<a id="minor-changes-2"></a> +### Minor Changes + +* Added a <code>community\.hrobot\.robot</code> module defaults group / action group\. Use with <code>group/community\.hrobot\.robot</code> to provide options for all Hetzner Robot modules \([https\://github\.com/ansible\-collections/community\.hrobot/pull/65](https\://github\.com/ansible\-collections/community\.hrobot/pull/65)\)\. + +<a id="v1-5-2"></a> +## v1\.5\.2 + +<a id="release-summary-7"></a> +### Release Summary + +Maintenance release with a documentation improvement\. + +<a id="minor-changes-3"></a> +### Minor Changes + +* The collection repository conforms to the [REUSE specification](https\://reuse\.software/spec/) except for the changelog fragments \([https\://github\.com/ansible\-collections/community\.hrobot/pull/60](https\://github\.com/ansible\-collections/community\.hrobot/pull/60)\)\. + +<a id="v1-5-1"></a> +## v1\.5\.1 + +<a id="release-summary-8"></a> +### Release Summary + +Maintenance release with small documentation fixes\. + +<a id="v1-5-0"></a> +## v1\.5\.0 + +<a id="release-summary-9"></a> +### Release Summary + +Maintenance release changing the way licenses are declared\. No functional changes\. + +<a id="minor-changes-4"></a> +### Minor Changes + +* All software licenses are now in the <code>LICENSES/</code> directory of the collection root\. Moreover\, <code>SPDX\-License\-Identifier\:</code> is used to declare the applicable license for every file that is not automatically generated \([https\://github\.com/ansible\-collections/community\.hrobot/pull/52](https\://github\.com/ansible\-collections/community\.hrobot/pull/52)\)\. + +<a id="v1-4-0"></a> +## v1\.4\.0 + +<a id="release-summary-10"></a> +### Release Summary + +Feature release\. + +<a id="minor-changes-5"></a> +### Minor Changes + +* robot inventory plugin \- allow to template <code>hetzner\_user</code> and <code>hetzner\_password</code> \([https\://github\.com/ansible\-collections/community\.hrobot/pull/49](https\://github\.com/ansible\-collections/community\.hrobot/pull/49)\)\. + +<a id="v1-3-1"></a> +## v1\.3\.1 + +<a id="release-summary-11"></a> +### Release Summary + +Maintenance release\. + +<a id="bugfixes-1"></a> +### Bugfixes + +* Include <code>simplified\_bsd\.txt</code> license file for the <code>robot</code> and <code>failover</code> module utils\. + +<a id="v1-3-0"></a> +## v1\.3\.0 + +<a id="release-summary-12"></a> +### Release Summary + +Feature and bugfix release\. + +<a id="minor-changes-6"></a> +### Minor Changes + +* Prepare collection for inclusion in an Execution Environment by declaring its dependencies \([https\://github\.com/ansible\-collections/community\.hrobot/pull/45](https\://github\.com/ansible\-collections/community\.hrobot/pull/45)\)\. + +<a id="bugfixes-2"></a> +### Bugfixes + +* robot inventory plugin \- do not crash if a server neither has name or primary IP set\. Instead\, fall back to using the server\'s number as the name\. This can happen if unnamed rack reservations show up in your server list \([https\://github\.com/ansible\-collections/community\.hrobot/issues/40](https\://github\.com/ansible\-collections/community\.hrobot/issues/40)\, [https\://github\.com/ansible\-collections/community\.hrobot/pull/47](https\://github\.com/ansible\-collections/community\.hrobot/pull/47)\)\. + +<a id="v1-2-3"></a> +## v1\.2\.3 + +<a id="release-summary-13"></a> +### Release Summary + +Docs update release\. + +<a id="v1-2-2"></a> +## v1\.2\.2 + +<a id="release-summary-14"></a> +### Release Summary + +Bugfix release\. + +<a id="bugfixes-3"></a> +### Bugfixes + +* boot \- fix incorrect handling of SSH authorized keys \([https\://github\.com/ansible\-collections/community\.hrobot/issues/32](https\://github\.com/ansible\-collections/community\.hrobot/issues/32)\, [https\://github\.com/ansible\-collections/community\.hrobot/pull/33](https\://github\.com/ansible\-collections/community\.hrobot/pull/33)\)\. + +<a id="v1-2-1"></a> +## v1\.2\.1 + +<a id="release-summary-15"></a> +### Release Summary + +Maintenance release\. + +<a id="minor-changes-7"></a> +### Minor Changes + +* Generic module HTTP support code \- fix usage of <code>fetch\_url</code> with changes in latest ansible\-core <code>devel</code> branch \([https\://github\.com/ansible\-collections/community\.hrobot/pull/30](https\://github\.com/ansible\-collections/community\.hrobot/pull/30)\)\. + +<a id="v1-2-0"></a> +## v1\.2\.0 + +<a id="release-summary-16"></a> +### Release Summary + +Feature release with multiple new modules\. + +<a id="minor-changes-8"></a> +### Minor Changes + +* Avoid internal ansible\-core module\_utils in favor of equivalent public API available since at least Ansible 2\.9 \([https\://github\.com/ansible\-collections/community\.hrobot/pull/18](https\://github\.com/ansible\-collections/community\.hrobot/pull/18)\)\. +* firewall \- rename option <code>whitelist\_hos</code> to <code>allowlist\_hos</code>\, keep old name as alias \([https\://github\.com/ansible\-collections/community\.hrobot/pull/15](https\://github\.com/ansible\-collections/community\.hrobot/pull/15)\)\. +* firewall\, firewall\_info \- add return value <code>allowlist\_hos</code>\, which contains the same value as <code>whitelist\_hos</code>\. The old name <code>whitelist\_hos</code> will be removed eventually \([https\://github\.com/ansible\-collections/community\.hrobot/pull/15](https\://github\.com/ansible\-collections/community\.hrobot/pull/15)\)\. +* robot module utils \- add <code>allow\_empty\_result</code> parameter to <code>plugin\_open\_url\_json</code> and <code>fetch\_url\_json</code> \([https\://github\.com/ansible\-collections/community\.hrobot/pull/16](https\://github\.com/ansible\-collections/community\.hrobot/pull/16)\)\. + +<a id="new-modules-1"></a> +### New Modules + +* community\.hrobot\.boot \- Set boot configuration +* community\.hrobot\.reset \- Reset a dedicated server +* community\.hrobot\.reverse\_dns \- Set or remove reverse DNS entry for IP +* community\.hrobot\.server \- Update server information +* community\.hrobot\.server\_info \- Query information on one or more servers +* community\.hrobot\.ssh\_key \- Add\, remove or update SSH key +* community\.hrobot\.ssh\_key\_info \- Query information on SSH keys + +<a id="v1-1-1"></a> +## v1\.1\.1 + +<a id="release-summary-17"></a> +### Release Summary + +Bugfix release which reduces the number of HTTPS queries for the modules and plugins\. + +<a id="bugfixes-4"></a> +### Bugfixes + +* robot \- force HTTP basic authentication to reduce number of HTTPS requests \([https\://github\.com/ansible\-collections/community\.hrobot/pull/9](https\://github\.com/ansible\-collections/community\.hrobot/pull/9)\)\. + +<a id="v1-1-0"></a> +## v1\.1\.0 + +<a id="release-summary-18"></a> +### Release Summary + +Release with a new inventory plugin\. + +<a id="new-plugins"></a> +### New Plugins + +<a id="inventory"></a> +#### Inventory + +* community\.hrobot\.robot \- Hetzner Robot inventory source + +<a id="v1-0-0"></a> +## v1\.0\.0 + +<a id="release-summary-19"></a> +### Release Summary + +The <code>community\.hrobot</code> continues the work on the Hetzner Robot modules from their state in <code>community\.general</code> 1\.2\.0\. The changes listed here are thus relative to the modules <code>community\.general\.hetzner\_\*</code>\. + +<a id="breaking-changes--porting-guide"></a> +### Breaking Changes / Porting Guide + +* firewall \- now requires the [ipaddress](https\://pypi\.org/project/ipaddress/) library \([https\://github\.com/ansible\-collections/community\.hrobot/pull/2](https\://github\.com/ansible\-collections/community\.hrobot/pull/2)\)\. diff --git a/ansible_collections/community/hrobot/CHANGELOG.md.license b/ansible_collections/community/hrobot/CHANGELOG.md.license new file mode 100644 index 000000000..edff8c768 --- /dev/null +++ b/ansible_collections/community/hrobot/CHANGELOG.md.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/ansible_collections/community/hrobot/CHANGELOG.rst b/ansible_collections/community/hrobot/CHANGELOG.rst index 9b7559cbf..847d3dbda 100644 --- a/ansible_collections/community/hrobot/CHANGELOG.rst +++ b/ansible_collections/community/hrobot/CHANGELOG.rst @@ -4,6 +4,71 @@ Community Hetzner Robot Collection Release Notes .. contents:: Topics +v1.9.1 +====== + +Release Summary +--------------- + +Bugfix release. + +Security Fixes +-------------- + +- robot inventory plugin - make sure all data received from the Hetzner robot service server is marked as unsafe, so remote code execution by obtaining texts that can be evaluated as templates is not possible (https://www.die-welt.net/2024/03/remote-code-execution-in-ansible-dynamic-inventory-plugins/, https://github.com/ansible-collections/community.hrobot/pull/99). + +v1.9.0 +====== + +Release Summary +--------------- + +Feature and maintenance release. + +Minor Changes +------------- + +- robot inventory plugin - the ``filters`` option has been renamed to ``simple_filters``. The old name still works until community.hrobot 2.0.0. Then it will change to allow more complex filtering with the ``community.library_inventory_filtering_v1`` collection's functionality (https://github.com/ansible-collections/community.hrobot/pull/94). + +Deprecated Features +------------------- + +- robot inventory plugin - the ``filters`` option has been renamed to ``simple_filters``. The old name will stop working in community.hrobot 2.0.0 (https://github.com/ansible-collections/community.hrobot/pull/94). + +v1.8.2 +====== + +Release Summary +--------------- + +Maintenance release with updated documentation. + +Bugfixes +-------- + +- Show more information (if available) from error messages (https://github.com/ansible-collections/community.hrobot/pull/89). + +v1.8.1 +====== + +Release Summary +--------------- + +Maintenance release with updated documentation. + +From this version on, community.hrobot is using the new `Ansible semantic markup +<https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_documenting.html#semantic-markup-within-module-documentation>`__ +in its documentation. If you look at documentation with the ansible-doc CLI tool +from ansible-core before 2.15, please note that it does not render the markup +correctly. You should be still able to read it in most cases, but you need +ansible-core 2.15 or later to see it as it is intended. Alternatively you can +look at `the devel docsite <https://docs.ansible.com/ansible/devel/collections/community/hrobot/>`__ +for the rendered HTML version of the documentation of the latest release. + +Known Issues +------------ + +- Ansible markup will show up in raw form on ansible-doc text output for ansible-core before 2.15. If you have trouble deciphering the documentation markup, please upgrade to ansible-core 2.15 (or newer), or read the HTML documentation on https://docs.ansible.com/ansible/devel/collections/community/hrobot/. v1.8.0 ====== @@ -226,7 +291,6 @@ Release Summary The ``community.hrobot`` continues the work on the Hetzner Robot modules from their state in ``community.general`` 1.2.0. The changes listed here are thus relative to the modules ``community.general.hetzner_*``. - Breaking Changes / Porting Guide -------------------------------- diff --git a/ansible_collections/community/hrobot/FILES.json b/ansible_collections/community/hrobot/FILES.json index 9576b95d8..54c28f1e6 100644 --- a/ansible_collections/community/hrobot/FILES.json +++ b/ansible_collections/community/hrobot/FILES.json @@ -25,7 +25,7 @@ "name": ".github/workflows/ansible-test.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3a0024831cf7cc7a832b0478ae964e70e3713af496ce78904f1c820b3878507c", + "chksum_sha256": "b221558d1b9e91f2f1b3087eca7455efea6016a313388315d94c748a736f6d0c", "format": 1 }, { @@ -46,28 +46,28 @@ "name": ".github/workflows/ee.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2ec44891b83956d4816fef844f14e692e56dcd9f46b96aa55dcfa838f1290181", + "chksum_sha256": "03c5a4a0a65ebe7d5b9683d95f2752cdbbcac4d4b8cca513d4332d80dd1c79c2", "format": 1 }, { "name": ".github/workflows/extra-tests.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1dddc4fefe3721d4daf55419948d65be8f05579a015b37e4229fbb1475ae3958", + "chksum_sha256": "3d4972a65972c0091b7343e287eba10382716e29fd184091b1f8b4df4892fe44", "format": 1 }, { "name": ".github/workflows/import-galaxy.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "220b0bab6530dfbbe6031eb7d7e569b20af32cfcb82b4bfa8d3e08e7450d9b89", + "chksum_sha256": "739c36223d6e0e6ccc98907c43cba53296e7b1ccd64a2d995c2ff21df4ab25a5", "format": 1 }, { "name": ".github/workflows/reuse.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c9cc8b1cebfde4ee00c680356325d514c3ee3fa792e04cc6f5d74740fbfd61b4", + "chksum_sha256": "bc2800b679cfe401b8c7a7188a8669f2717425390947fd0dba6477797d2dc614", "format": 1 }, { @@ -137,7 +137,7 @@ "name": "changelogs/changelog.yaml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3a3089a66ec4db61793fea71c17024c3aeef4e89818d70ea3d15a67bb2b7a1a9", + "chksum_sha256": "7bb1dd839047930188a470f49ab846872b8b5fed15a0ad79f2a4f6badc7ca08f", "format": 1 }, { @@ -151,7 +151,7 @@ "name": "changelogs/config.yaml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "34aff4539b48607175563a83f71ec1c66ee23a2e94906915fe3ac3d89a4d68ef", + "chksum_sha256": "a7b8fa9406e8d12b8783432c8dcbec5e940b502649eb8d4c1bbc18bcac0c7ede", "format": 1 }, { @@ -235,7 +235,7 @@ "name": "plugins/inventory/robot.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f012c1189cc2df209e97e7dd5fa8d2502f192abeb922d7dff3d4918fe3f9ca83", + "chksum_sha256": "08386e031100da8e3ae8d8a76fdf511b71ebce6d5b9648dc24f32784ee497fda", "format": 1 }, { @@ -256,7 +256,7 @@ "name": "plugins/module_utils/robot.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "dcfd4d5f6854cc2c82f9239d05c0625fdcf38b18b67b4cab8ecdf391afdb6e9e", + "chksum_sha256": "61fd87bec43eae7bc08f2414c51b4f479ebca17d7e0be5d9d337c75392dd6bf0", "format": 1 }, { @@ -270,70 +270,70 @@ "name": "plugins/modules/boot.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f9f0adbcd0ce63cebde36f20795961d5c678465b764bd037900cf3c14fb540a7", + "chksum_sha256": "6e602be89c58a047b8b0874a462e950340f1ae5c0066876efc3c6826f9fd1464", "format": 1 }, { "name": "plugins/modules/failover_ip.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c22701e1a41409a583dc8d9bc8f3aee0c5caf61711d1796729c571ce6baf68bc", + "chksum_sha256": "73945727cd5ebb8330f0089d7ac6c429b457863fffc0fbfb3fd3309041b23c4c", "format": 1 }, { "name": "plugins/modules/failover_ip_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a732a481bf7bd2d7956e2b7c73b58e4631dff3a491a38cea47aafa7fc87d70b3", + "chksum_sha256": "6876f306910f6b3339eb45482bba2563789b92a529f026e174e1d35f4bf6e39d", "format": 1 }, { "name": "plugins/modules/firewall.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8fd6d3567e7077bd4f94c40be87e6519f5e3fe24dcb60559b3c28c133fe1d0e5", + "chksum_sha256": "91a1096959175c8a038b4baeadd13cea05f852579f7f09542f653136bd9f9b6e", "format": 1 }, { "name": "plugins/modules/firewall_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2492c517ba7e4440913d7760f1cb47b33fe5dbc41ae6e738d08986b0eacdcbce", + "chksum_sha256": "c4b7b4012cda86c3ad336c148ceafead1454c3a8de2325372dbb3ba797ca8024", "format": 1 }, { "name": "plugins/modules/reset.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c326bd880106c020c0a923b9b2239e5fa7ca02f92df5a2100aef8fd8a2ea83ef", + "chksum_sha256": "e6a78514fec243ac08dbdb9f258b297b9e10dd3374b98941694e9ef67008c22a", "format": 1 }, { "name": "plugins/modules/reverse_dns.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "64521ba301cc273f59deb696ab80d8529f3297d9e1dc8d2470926f45ff114c7b", + "chksum_sha256": "5a976d175cc922ecb5cc04d2c076a84794b5c8033369870ff648344fa2c6c4e9", "format": 1 }, { "name": "plugins/modules/server.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2448b78e391940eb6fb4a955c1d24f5e54a1f519d24dc3e60b30efb4cca916f2", + "chksum_sha256": "7d2fa319fa2ed98d511daab1f576d46d551b4785d3a9e18a7d44d95b43234934", "format": 1 }, { "name": "plugins/modules/server_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "08f5cb04db19a18ca3ec6fc3cfb01adf6f174dc94c4befb826f854ac0fab42d7", + "chksum_sha256": "057ee56dbd104fb5bd2031ebef68c6c93cf378342029cab26e4c671d9346716c", "format": 1 }, { "name": "plugins/modules/ssh_key.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "56d3a5ef901a3c692d6f5f3dc7a07da8a384fdfefb1d7ad7bcde0e7cae0092ae", + "chksum_sha256": "8df71f0d30ffbfc928851111c023ee1c2907194a73e1f9abf2b485c09dcaa823", "format": 1 }, { @@ -347,7 +347,7 @@ "name": "plugins/modules/v_switch.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0769c7829fc91038fb4b7ea446d3a5f3fafc3a3d0ec4c6085158d8ae741fe053", + "chksum_sha256": "bfd0a37f238dead342b88bcce0ea8f6d1e45819d6e1e1335f1cfef450529828d", "format": 1 }, { @@ -431,7 +431,7 @@ "name": "tests/sanity/extra/extra-docs.json", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "63af024dcda47dda7e3cead05953d33c858853d2adc046efb47af28a6a0dc96b", + "chksum_sha256": "6c7fbc8a07fa803ce062387232eb0d0198a311f5347493f06c19a07aa45a9bf6", "format": 1 }, { @@ -445,7 +445,7 @@ "name": "tests/sanity/extra/extra-docs.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "00ae2a5eeec7f3a621074473ee4d0d16f763c67e1c6c1b2f4b7dcd3ca171262c", + "chksum_sha256": "c52e316daf1292bbb063be19429fd1f06e02bce3c9d4622a8dfc61fa3af06688", "format": 1 }, { @@ -582,6 +582,34 @@ "format": 1 }, { + "name": "tests/sanity/ignore-2.16.txt", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5264853edb2c6ff138f5496111c1e758a3a54b61e82d96c0072cb9429fb31c6e", + "format": 1 + }, + { + "name": "tests/sanity/ignore-2.16.txt.license", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6eb915239f9f35407fa68fdc41ed6522f1fdcce11badbdcd6057548023179ac1", + "format": 1 + }, + { + "name": "tests/sanity/ignore-2.17.txt", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5264853edb2c6ff138f5496111c1e758a3a54b61e82d96c0072cb9429fb31c6e", + "format": 1 + }, + { + "name": "tests/sanity/ignore-2.17.txt.license", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6eb915239f9f35407fa68fdc41ed6522f1fdcce11badbdcd6057548023179ac1", + "format": 1 + }, + { "name": "tests/sanity/ignore-2.9.txt", "ftype": "file", "chksum_type": "sha256", @@ -620,7 +648,7 @@ "name": "tests/unit/plugins/inventory/test_robot.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1e7aebcb567bfb2c8dd055e5ea6ccb4cb175b4e7df992868e0ef0df2b47cbaf1", + "chksum_sha256": "673ffae43e3a3584719643a42bbdd33321b2b8331629a9d069793c3925d21c35", "format": 1 }, { @@ -634,14 +662,14 @@ "name": "tests/unit/plugins/module_utils/test_failover.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "19106763b057e212a13597775a82f939f5b6959b317e93fe3188a64284d8797f", + "chksum_sha256": "d6072cde4dbaef7af6400d9e417c7e647607628826c732dbc1b16f53f2e46f6c", "format": 1 }, { "name": "tests/unit/plugins/module_utils/test_robot.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c8ccfce1d5a536b29c4ce5ab7529e75dc893e4d15f66032fc7b6fa9c6af4e1f0", + "chksum_sha256": "20bb76b45cfd9c002089324c941f9ed34e48635781b30c3a808ce3892bbfae03", "format": 1 }, { @@ -743,6 +771,13 @@ "format": 1 }, { + "name": "tests/unit/requirements.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "999b6bb4a4234b1f38abb63cbd57d40af2d93bcff2260ab088e09157a055abaf", + "format": 1 + }, + { "name": "tests/config.yml", "ftype": "file", "chksum_type": "sha256", @@ -750,17 +785,24 @@ "format": 1 }, { - "name": "tests/requirements.yml", + "name": "CHANGELOG.md", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2c4facb0c77d486fd61f1ea78cd2bee7c6cf833fc4dd328b57a9a440efe43db3", + "format": 1 + }, + { + "name": "CHANGELOG.md.license", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d556aaf12dcf49749ad88e27cb3b2c9995de47c1eccde8b73de744b21ca218cc", + "chksum_sha256": "6eb915239f9f35407fa68fdc41ed6522f1fdcce11badbdcd6057548023179ac1", "format": 1 }, { "name": "CHANGELOG.rst", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "240999c1e8b017228a03f0c6fb48e35a637e650fa4fb022fdc2c35d480ba7615", + "chksum_sha256": "ca10d6a2a30e1165b9325897d7c6335ff8b3a50859742e2e4333070df0e6c38f", "format": 1 }, { @@ -781,7 +823,7 @@ "name": "README.md", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7ffc02a04b50194cf13c5b6b54372e3e29939dafc7efe965ca5193d27f64b6ea", + "chksum_sha256": "b26ea8090f24cde8afb282f7779abf6ce363edbf65068631c38984c5ed51ba70", "format": 1 }, { diff --git a/ansible_collections/community/hrobot/MANIFEST.json b/ansible_collections/community/hrobot/MANIFEST.json index 74cd2a6f1..5fd6295d8 100644 --- a/ansible_collections/community/hrobot/MANIFEST.json +++ b/ansible_collections/community/hrobot/MANIFEST.json @@ -2,7 +2,7 @@ "collection_info": { "namespace": "community", "name": "hrobot", - "version": "1.8.0", + "version": "1.9.1", "authors": [ "Felix Fontein (github.com/felixfontein)" ], @@ -30,7 +30,7 @@ "name": "FILES.json", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1d5553b60ed857cfc979fd52b7531a8135bec6bde395b4ec3e1356daa2fab3bb", + "chksum_sha256": "cada2fa56571e4857ace197d0dd1c09e665fdd718cea048c0327ba8ef3447245", "format": 1 }, "format": 1 diff --git a/ansible_collections/community/hrobot/README.md b/ansible_collections/community/hrobot/README.md index 2f78a9aef..44ee9ddcd 100644 --- a/ansible_collections/community/hrobot/README.md +++ b/ansible_collections/community/hrobot/README.md @@ -15,7 +15,7 @@ Please note that this collection does **not** support Windows targets. ## Tested with Ansible -Tested with the current Ansible 2.9, ansible-base 2.10, ansible-core 2.11, ansible-core 2.12, ansible-core 2.13, and ansible-core 2.14 releases and the current development version of ansible-core. Ansible versions before 2.9.10 are not supported. +Tested with the current Ansible 2.9, ansible-base 2.10, ansible-core 2.11, ansible-core 2.12, ansible-core 2.13, ansible-core 2.14, ansible-core 2.15, and ansible-core 2.16 releases and the current development version of ansible-core. Ansible versions before 2.9.10 are not supported. ## External requirements @@ -37,7 +37,7 @@ If you use the Ansible package and do not update collections independently, use - `community.hrobot.failover_ip_info` module - `community.hrobot.firewall` module - `community.hrobot.firewall_info` module -- `community.hrobot.hrobot` inventory plugin +- `community.hrobot.robot` inventory plugin You can find [documentation for the modules and plugins in this collection here](https://docs.ansible.com/ansible/devel/collections/community/hrobot/). @@ -64,7 +64,7 @@ You can find more information in the [developer guide for collections](https://d ## Release notes -See the [changelog](https://github.com/ansible-collections/community.hrobot/tree/main/CHANGELOG.rst). +See the [changelog](https://github.com/ansible-collections/community.hrobot/tree/main/CHANGELOG.md). ## More information diff --git a/ansible_collections/community/hrobot/changelogs/changelog.yaml b/ansible_collections/community/hrobot/changelogs/changelog.yaml index 94785155c..ff49e627a 100644 --- a/ansible_collections/community/hrobot/changelogs/changelog.yaml +++ b/ansible_collections/community/hrobot/changelogs/changelog.yaml @@ -210,3 +210,73 @@ releases: - 76-firewall-ipv6-output.yml - 77-firewall-server_number.yml release_date: '2023-03-15' + 1.8.1: + changes: + known_issues: + - Ansible markup will show up in raw form on ansible-doc text output for ansible-core + before 2.15. If you have trouble deciphering the documentation markup, please + upgrade to ansible-core 2.15 (or newer), or read the HTML documentation on + https://docs.ansible.com/ansible/devel/collections/community/hrobot/. + release_summary: 'Maintenance release with updated documentation. + + + From this version on, community.hrobot is using the new `Ansible semantic + markup + + <https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_documenting.html#semantic-markup-within-module-documentation>`__ + + in its documentation. If you look at documentation with the ansible-doc CLI + tool + + from ansible-core before 2.15, please note that it does not render the markup + + correctly. You should be still able to read it in most cases, but you need + + ansible-core 2.15 or later to see it as it is intended. Alternatively you + can + + look at `the devel docsite <https://docs.ansible.com/ansible/devel/collections/community/hrobot/>`__ + + for the rendered HTML version of the documentation of the latest release. + + ' + fragments: + - 1.8.1.yml + - semantic-markup.yml + release_date: '2023-06-27' + 1.8.2: + changes: + bugfixes: + - Show more information (if available) from error messages (https://github.com/ansible-collections/community.hrobot/pull/89). + release_summary: Maintenance release with updated documentation. + fragments: + - 1.8.2.yml + - 89-firewall.yml + release_date: '2023-11-11' + 1.9.0: + changes: + deprecated_features: + - robot inventory plugin - the ``filters`` option has been renamed to ``simple_filters``. + The old name will stop working in community.hrobot 2.0.0 (https://github.com/ansible-collections/community.hrobot/pull/94). + minor_changes: + - robot inventory plugin - the ``filters`` option has been renamed to ``simple_filters``. + The old name still works until community.hrobot 2.0.0. Then it will change + to allow more complex filtering with the ``community.library_inventory_filtering_v1`` + collection's functionality (https://github.com/ansible-collections/community.hrobot/pull/94). + release_summary: Feature and maintenance release. + fragments: + - 1.9.0.yml + - 94-inventory-filters.yml + release_date: '2024-01-21' + 1.9.1: + changes: + release_summary: Bugfix release. + security_fixes: + - robot inventory plugin - make sure all data received from the Hetzner robot + service server is marked as unsafe, so remote code execution by obtaining + texts that can be evaluated as templates is not possible (https://www.die-welt.net/2024/03/remote-code-execution-in-ansible-dynamic-inventory-plugins/, + https://github.com/ansible-collections/community.hrobot/pull/99). + fragments: + - 1.9.1.yml + - inventory-rce.yml + release_date: '2024-03-16' diff --git a/ansible_collections/community/hrobot/changelogs/config.yaml b/ansible_collections/community/hrobot/changelogs/config.yaml index 4d6ee1a9b..ed2ab2a71 100644 --- a/ansible_collections/community/hrobot/changelogs/config.yaml +++ b/ansible_collections/community/hrobot/changelogs/config.yaml @@ -11,6 +11,9 @@ keep_fragments: false mention_ancestor: true new_plugins_after_name: removed_features notesdir: fragments +output_formats: +- rst +- md prelude_section_name: release_summary prelude_section_title: Release Summary sections: diff --git a/ansible_collections/community/hrobot/plugins/inventory/robot.py b/ansible_collections/community/hrobot/plugins/inventory/robot.py index 1d5af4537..19a2f1aa4 100644 --- a/ansible_collections/community/hrobot/plugins/inventory/robot.py +++ b/ansible_collections/community/hrobot/plugins/inventory/robot.py @@ -26,7 +26,7 @@ DOCUMENTATION = r""" - ansible.builtin.inventory_cache - community.hrobot.robot notes: - - The I(hetzner_user) and I(hetzner_password) options can be templated. + - The O(hetzner_user) and O(hetzner_password) options can be templated. options: plugin: description: Token that ensures this is a source file for the plugin. @@ -38,13 +38,17 @@ DOCUMENTATION = r""" hetzner_password: env: - name: HROBOT_API_PASSWORD - filters: + simple_filters: description: - A dictionary of filter value pairs. - Available filters are listed here are keys of server like C(status) or C(server_ip). - See U(https://robot.your-server.de/doc/webservice/en.html#get-server) for all values that can be used. + - This option has been renamed from O(filters) to O(simple_filters) in community.hrobot 1.9.0. + The old name can still be used until community.hrobot 2.0.0. type: dict default: {} + aliases: + - filters """ EXAMPLES = r""" @@ -63,7 +67,7 @@ hetzner_password: '{{ (lookup("community.sops.sops", "keys/hetzner.sops.yaml") | # Example using constructed features to create groups plugin: community.hrobot.robot -filters: +simple_filters: status: ready traffic: unlimited # keyed_groups may be used to create custom groups @@ -81,6 +85,7 @@ from ansible.errors import AnsibleError from ansible.plugins.inventory import BaseInventoryPlugin, Constructable, Cacheable from ansible.template import Templar from ansible.utils.display import Display +from ansible.utils.unsafe_proxy import wrap_var as make_unsafe from ansible_collections.community.hrobot.plugins.module_utils.robot import ( BASE_URL, @@ -109,10 +114,18 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable): def parse(self, inventory, loader, path, cache=True): super(InventoryModule, self).parse(inventory, loader, path) servers = {} - config = self._read_config_data(path) + orig_config = self._read_config_data(path) self.load_cache_plugin() cache_key = self.get_cache_key(path) + if 'filters' in orig_config: + display.deprecated( + 'The `filters` option of the community.hrobot.robot inventory plugin has been renamed to `simple_filters`. ' + 'The old name will stop working in community.hrobot 2.0.0.', + collection_name='community.hrobot', + version='2.0.0', + ) + self.templar = Templar(loader=loader) # cache may be True or False at this point to indicate if the inventory is being refreshed @@ -143,7 +156,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable): self.populate(servers) def populate(self, servers): - filters = self.get_option('filters') + filters = self.get_option('simple_filters') strict = self.get_option('strict') server_lists = [] for server in servers: @@ -162,9 +175,9 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable): self.inventory.add_host(server_name) server_lists.append(server_name) if 'server_ip' in s: - self.inventory.set_variable(server_name, 'ansible_host', s['server_ip']) + self.inventory.set_variable(server_name, 'ansible_host', make_unsafe(s['server_ip'])) for hostvar, hostval in s.items(): - self.inventory.set_variable(server_name, "{0}_{1}".format('hrobot', hostvar), hostval) + self.inventory.set_variable(server_name, "{0}_{1}".format('hrobot', hostvar), make_unsafe(hostval)) # Composed variables server_vars = self.inventory.get_host(server_name).get_vars() diff --git a/ansible_collections/community/hrobot/plugins/module_utils/robot.py b/ansible_collections/community/hrobot/plugins/module_utils/robot.py index 034a3fc48..f01409083 100644 --- a/ansible_collections/community/hrobot/plugins/module_utils/robot.py +++ b/ansible_collections/community/hrobot/plugins/module_utils/robot.py @@ -8,6 +8,7 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type +from ansible.module_utils.common.text.converters import to_native from ansible.module_utils.six import PY3 from ansible.module_utils.six.moves.urllib.error import HTTPError from ansible.module_utils.urls import fetch_url, open_url @@ -33,6 +34,30 @@ def get_x_www_form_urlenconded_dict_from_list(key, values): return dict(('{key}[{index}]'.format(key=key, index=i), x) for i, x in enumerate(values)) +def _format_list(obj): + if not isinstance(obj, (list, tuple)): + return to_native(obj) + return [_format_list(e) for e in obj] + + +def format_error_msg(error): + # Reference: https://robot.hetzner.com/doc/webservice/en.html#errors + msg = 'Request failed: {0} {1} ({2})'.format( + error['status'], + error['code'], + error['message'], + ) + if error.get('missing'): + msg += '. Missing input parameters: {0}'.format(_format_list(error['missing'])) + if error.get('invalid'): + msg += '. Invalid input parameters: {0}'.format(_format_list(error['invalid'])) + if error.get('max_request') is not None: + msg += '. Maximum allowed requests: {0}'.format(error['max_request']) + if error.get('interval') is not None: + msg += '. Time interval in seconds: {0}'.format(error['interval']) + return msg + + class PluginException(Exception): def __init__(self, message): super(PluginException, self).__init__(message) @@ -85,11 +110,7 @@ def plugin_open_url_json(plugin, url, method='GET', timeout=10, data=None, heade if accept_errors: if result['error']['code'] in accept_errors: return result, result['error']['code'] - raise PluginException('Request failed: {0} {1} ({2})'.format( - result['error']['status'], - result['error']['code'], - result['error']['message'] - )) + raise PluginException(format_error_msg(result['error'])) return result, None except ValueError: raise PluginException('Cannot decode content retrieved from {0}'.format(url)) @@ -125,11 +146,7 @@ def fetch_url_json(module, url, method='GET', timeout=10, data=None, headers=Non if accept_errors: if result['error']['code'] in accept_errors: return result, result['error']['code'] - module.fail_json(msg='Request failed: {0} {1} ({2})'.format( - result['error']['status'], - result['error']['code'], - result['error']['message'] - )) + module.fail_json(msg=format_error_msg(result['error']), error=result['error']) return result, None except ValueError: module.fail_json(msg='Cannot decode content retrieved from {0}'.format(url)) diff --git a/ansible_collections/community/hrobot/plugins/modules/boot.py b/ansible_collections/community/hrobot/plugins/modules/boot.py index 64917d9b8..bcf6f3c47 100644 --- a/ansible_collections/community/hrobot/plugins/modules/boot.py +++ b/ansible_collections/community/hrobot/plugins/modules/boot.py @@ -46,31 +46,31 @@ options: description: - If this option is provided, all special boot configurations are removed and the installed operating system will be booted up next (assuming it is bootable). - - Precisely one of I(regular_boot), I(rescue), I(install_linux), I(install_vnc), - I(install_windows), I(install_plesk), and I(install_cpanel) must be provided. + - Precisely one of O(regular_boot), O(rescue), O(install_linux), O(install_vnc), + O(install_windows), O(install_plesk), and O(install_cpanel) must be provided. type: bool choices: - true rescue: description: - If this option is provided, the rescue system will be activated for the next boot. - - Precisely one of I(regular_boot), I(rescue), I(install_linux), I(install_vnc), - I(install_windows), I(install_plesk), and I(install_cpanel) must be provided. + - Precisely one of O(regular_boot), O(rescue), O(install_linux), O(install_vnc), + O(install_windows), O(install_plesk), and O(install_cpanel) must be provided. type: dict suboptions: os: description: - The operating system to use for the rescue system. Possible choices can change over time. - - Currently, C(linux), C(linuxold), C(freebsd), C(freebsdold), C(freebsdax), - C(freebsdbetaax), C(vkvm), and C(vkvmold) seem to be available. + - Currently, V(linux), V(linuxold), V(freebsd), V(freebsdold), V(freebsdax), + V(freebsdbetaax), V(vkvm), and V(vkvmold) seem to be available. type: str required: true arch: description: - The architecture to use for the rescue system. - Not all architectures are available for all operating systems. - - Defaults to C(64). + - Defaults to V(64). type: int choices: - 32 @@ -87,8 +87,8 @@ options: install_linux: description: - If this option is provided, a Linux system install will be activated for the next boot. - - Precisely one of I(regular_boot), I(rescue), I(install_linux), I(install_vnc), - I(install_windows), I(install_plesk), and I(install_cpanel) must be provided. + - Precisely one of O(regular_boot), O(rescue), O(install_linux), O(install_vnc), + O(install_windows), O(install_plesk), and O(install_cpanel) must be provided. type: dict suboptions: dist: @@ -100,7 +100,7 @@ options: description: - The architecture to use for the install. - Not all architectures are available for all distributions. - - Defaults to C(64). + - Defaults to V(64). type: int choices: - 32 @@ -122,8 +122,8 @@ options: install_vnc: description: - If this option is provided, a VNC installation will be activated for the next boot. - - Precisely one of I(regular_boot), I(rescue), I(install_linux), I(install_vnc), - I(install_windows), I(install_plesk), and I(install_cpanel) must be provided. + - Precisely one of O(regular_boot), O(rescue), O(install_linux), O(install_vnc), + O(install_windows), O(install_plesk), and O(install_cpanel) must be provided. type: dict suboptions: dist: @@ -135,7 +135,7 @@ options: description: - The architecture to use for the install. - Not all architectures are available for all distributions. - - Defaults to C(64). + - Defaults to V(64). type: int choices: - 32 @@ -148,8 +148,8 @@ options: install_windows: description: - If this option is provided, a Windows installation will be activated for the next boot. - - Precisely one of I(regular_boot), I(rescue), I(install_linux), I(install_vnc), - I(install_windows), I(install_plesk), and I(install_cpanel) must be provided. + - Precisely one of O(regular_boot), O(rescue), O(install_linux), O(install_vnc), + O(install_windows), O(install_plesk), and O(install_cpanel) must be provided. type: dict suboptions: lang: @@ -160,8 +160,8 @@ options: install_plesk: description: - If this option is provided, a Plesk installation will be activated for the next boot. - - Precisely one of I(regular_boot), I(rescue), I(install_linux), I(install_vnc), - I(install_windows), I(install_plesk), and I(install_cpanel) must be provided. + - Precisely one of O(regular_boot), O(rescue), O(install_linux), O(install_vnc), + O(install_windows), O(install_plesk), and O(install_cpanel) must be provided. type: dict suboptions: dist: @@ -173,7 +173,7 @@ options: description: - The architecture to use for the install. - Not all architectures are available for all distributions. - - Defaults to C(64). + - Defaults to V(64). type: int choices: - 32 @@ -191,8 +191,8 @@ options: install_cpanel: description: - If this option is provided, a cPanel installation will be activated for the next boot. - - Precisely one of I(regular_boot), I(rescue), I(install_linux), I(install_vnc), - I(install_windows), I(install_plesk), and I(install_cpanel) must be provided. + - Precisely one of O(regular_boot), O(rescue), O(install_linux), O(install_vnc), + O(install_windows), O(install_plesk), and O(install_cpanel) must be provided. type: dict suboptions: dist: @@ -204,7 +204,7 @@ options: description: - The architecture to use for the install. - Not all architectures are available for all distributions. - - Defaults to C(64). + - Defaults to V(64). type: int choices: - 32 @@ -266,7 +266,7 @@ password: - The root password for the active boot configuration, if available. - For non-rescue boot configurations, it is avised to change the root password as soon as possible. - returned: success and if a boot configuration other than C(regular_boot) is active + returned: success and if RV(configuration_type) is not V(regular_boot) type: str ''' diff --git a/ansible_collections/community/hrobot/plugins/modules/failover_ip.py b/ansible_collections/community/hrobot/plugins/modules/failover_ip.py index da2da356a..e5d0fdae7 100644 --- a/ansible_collections/community/hrobot/plugins/modules/failover_ip.py +++ b/ansible_collections/community/hrobot/plugins/modules/failover_ip.py @@ -44,7 +44,7 @@ options: state: description: - Defines whether the IP will be routed or not. - - If set to C(routed), I(value) must be specified. + - If set to V(routed), O(value) must be specified. type: str choices: - routed @@ -53,7 +53,7 @@ options: value: description: - The new value for the failover IP address. - - Required when setting I(state) to C(routed). + - Required when setting O(state) to V(routed). type: str timeout: description: @@ -85,12 +85,12 @@ RETURN = r''' value: description: - The value of the failover IP. - - Will be C(none) if the IP is unrouted. + - Will be V(none) if the IP is unrouted. returned: success type: str state: description: - - Will be C(routed) or C(unrouted). + - Will be V(routed) or V(unrouted). returned: success type: str ''' diff --git a/ansible_collections/community/hrobot/plugins/modules/failover_ip_info.py b/ansible_collections/community/hrobot/plugins/modules/failover_ip_info.py index b656b0499..1db0d1b2c 100644 --- a/ansible_collections/community/hrobot/plugins/modules/failover_ip_info.py +++ b/ansible_collections/community/hrobot/plugins/modules/failover_ip_info.py @@ -59,12 +59,12 @@ RETURN = r''' value: description: - The value of the failover IP. - - Will be C(none) if the IP is unrouted. + - Will be V(none) if the IP is unrouted. returned: success type: str state: description: - - Will be C(routed) or C(unrouted). + - Will be V(routed) or V(unrouted). returned: success type: str failover_ip: diff --git a/ansible_collections/community/hrobot/plugins/modules/firewall.py b/ansible_collections/community/hrobot/plugins/modules/firewall.py index 2677a1186..8f158eaa6 100644 --- a/ansible_collections/community/hrobot/plugins/modules/firewall.py +++ b/ansible_collections/community/hrobot/plugins/modules/firewall.py @@ -44,14 +44,14 @@ options: server_ip: description: - The server's main IP address. - - Exactly one of I(server_ip) and I(server_number) must be specified. + - Exactly one of O(server_ip) and O(server_number) must be specified. - Note that Hetzner deprecated identifying the server's firewall by the server's main IP. - Using this option can thus stop working at any time in the future. Use I(server_number) instead. + Using this option can thus stop working at any time in the future. Use O(server_number) instead. type: str server_number: description: - The server's number. - - Exactly one of I(server_ip) and I(server_number) must be specified. + - Exactly one of O(server_ip) and O(server_number) must be specified. type: int version_added: 1.8.0 filter_ipv6: @@ -69,7 +69,7 @@ options: state: description: - Status of the firewall. - - Firewall is active if state is C(present), and disabled if state is C(absent). + - Firewall is active if state is V(present), and disabled if state is V(absent). type: str default: present choices: [ present, absent ] @@ -93,11 +93,14 @@ options: name: description: - Name of the firewall rule. + - Note that Hetzner restricts the characters that can be used for rule names. At the moment, only + letters C(a-z), C(A-Z), space, and the symbols C(.), C(-), C(+), C(_), and C(@) are allowed. type: str ip_version: description: - Internet protocol version. - - Leave away to filter both protocols. Note that in that case, none of I(dst_ip), I(src_ip), or I(protocol) can be specified. + - Leave away to filter both protocols. Note that in that case, none of O(rules.input[].dst_ip), + O(rules.input[].src_ip), or O(rules.input[].protocol) can be specified. type: str dst_ip: description: @@ -124,8 +127,8 @@ options: tcp_flags: description: - TCP flags or logical combination of flags. - - Flags supported by Hetzner are C(syn), C(fin), C(rst), C(psh) and C(urg). - - They can be combined with C(|) (logical or) and C(&) (logical and). + - Flags supported by Hetzner are V(syn), V(fin), V(rst), V(psh) and V(urg). + - They can be combined with V(|) (logical or) and V(&) (logical and). - See L(the documentation,https://wiki.hetzner.de/index.php/Robot_Firewall/en#Parameter) for more information. type: str @@ -145,11 +148,14 @@ options: name: description: - Name of the firewall rule. + - Note that Hetzner restricts the characters that can be used for rule names. At the moment, only + letters C(a-z), C(A-Z), space, and the symbols C(.), C(-), C(+), C(_), and C(@) are allowed. type: str ip_version: description: - Internet protocol version. - - Leave away to filter both protocols. Note that in that case, none of I(dst_ip), I(src_ip), or I(protocol) can be specified. + - Leave away to filter both protocols. Note that in that case, none of O(rules.output[].dst_ip), + O(rules.output[].src_ip), or O(rules.output[].protocol) can be specified. type: str dst_ip: description: @@ -176,8 +182,8 @@ options: tcp_flags: description: - TCP flags or logical combination of flags. - - Flags supported by Hetzner are C(syn), C(fin), C(rst), C(psh) and C(urg). - - They can be combined with C(|) (logical or) and C(&) (logical and). + - Flags supported by Hetzner are V(syn), V(fin), V(rst), V(psh) and V(urg). + - They can be combined with V(|) (logical or) and V(&) (logical and). - See L(the documentation,https://wiki.hetzner.de/index.php/Robot_Firewall/en#Parameter) for more information. type: str @@ -230,7 +236,8 @@ EXAMPLES = r''' allowlist_hos: true rules: input: - - name: Allow ICMP protocol, so you can ping your server + - name: Allow ICMP protocol + # This is needed so you can ping your server ip_version: ipv4 protocol: icmp action: accept @@ -241,7 +248,8 @@ EXAMPLES = r''' dst_port: '32768-65535' tcp_flags: ack action: accept - - name: Allow everything to ports 20-23 from 4.3.2.1/24 (IPv4 only) + - name: Allow restricted access from some known IPv4 addresses + # Allow everything to ports 20-23 from 4.3.2.1/24 (IPv4 only) ip_version: ipv4 src_ip: 4.3.2.1/24 dst_port: '20-23' @@ -270,7 +278,7 @@ firewall: port: description: - Switch port of firewall. - - C(main) or C(kvm). + - V(main) or V(kvm). type: str sample: main server_ip: @@ -286,9 +294,9 @@ firewall: status: description: - Status of the firewall. - - C(active) or C(disabled). - - Will be C(in process) if the firewall is currently updated, and - I(wait_for_configured) is set to C(false) or I(timeout) to a too small value. + - V(active) or V(disabled). + - Will be V(in process) if the firewall is currently updated, and + O(wait_for_configured) is set to V(false) or O(timeout) to a too small value. type: str sample: active allowlist_hos: @@ -300,7 +308,7 @@ firewall: whitelist_hos: description: - Whether Hetzner services have access. - - Old name of return value C(allowlist_hos), will be removed eventually. + - Old name of return value V(allowlist_hos), will be removed eventually. type: bool sample: true rules: @@ -360,7 +368,7 @@ firewall: action: description: - Action if rule matches. - - C(accept) or C(discard). + - V(accept) or V(discard). type: str sample: accept choices: @@ -418,7 +426,7 @@ firewall: action: description: - Action if rule matches. - - C(accept) or C(discard). + - V(accept) or V(discard). type: str sample: accept choices: diff --git a/ansible_collections/community/hrobot/plugins/modules/firewall_info.py b/ansible_collections/community/hrobot/plugins/modules/firewall_info.py index 49f98ab64..f72e253d7 100644 --- a/ansible_collections/community/hrobot/plugins/modules/firewall_info.py +++ b/ansible_collections/community/hrobot/plugins/modules/firewall_info.py @@ -37,14 +37,14 @@ options: server_ip: description: - The server's main IP address. - - Exactly one of I(server_ip) and I(server_number) must be specified. + - Exactly one of O(server_ip) and O(server_number) must be specified. - Note that Hetzner deprecated identifying the server's firewall by the server's main IP. - Using this option can thus stop working at any time in the future. Use I(server_number) instead. + Using this option can thus stop working at any time in the future. Use O(server_number) instead. type: str server_number: description: - The server's number. - - Exactly one of I(server_ip) and I(server_number) must be specified. + - Exactly one of O(server_ip) and O(server_number) must be specified. type: int version_added: 1.8.0 wait_for_configured: @@ -94,7 +94,7 @@ firewall: port: description: - Switch port of firewall. - - C(main) or C(kvm). + - V(main) or V(kvm). type: str sample: main filter_ipv6: @@ -115,9 +115,9 @@ firewall: status: description: - Status of the firewall. - - C(active) or C(disabled). - - Will be C(in process) if the firewall is currently updated, and - I(wait_for_configured) is set to C(false) or I(timeout) to a too small value. + - V(active) or V(disabled). + - Will be V(in process) if the firewall is currently updated, and + O(wait_for_configured) is set to V(false) or O(timeout) to a too small value. type: str sample: active allowlist_hos: @@ -129,7 +129,7 @@ firewall: whitelist_hos: description: - Whether Hetzner services have access. - - Old name of return value C(allowlist_hos), will be removed eventually. + - Old name of return value V(allowlist_hos), will be removed eventually. type: bool sample: true rules: @@ -189,7 +189,7 @@ firewall: action: description: - Action if rule matches. - - C(accept) or C(discard). + - V(accept) or V(discard). type: str sample: accept choices: @@ -247,7 +247,7 @@ firewall: action: description: - Action if rule matches. - - C(accept) or C(discard). + - V(accept) or V(discard). type: str sample: accept choices: diff --git a/ansible_collections/community/hrobot/plugins/modules/reset.py b/ansible_collections/community/hrobot/plugins/modules/reset.py index d367936e0..eaeaa5853 100644 --- a/ansible_collections/community/hrobot/plugins/modules/reset.py +++ b/ansible_collections/community/hrobot/plugins/modules/reset.py @@ -40,11 +40,11 @@ options: reset_type: description: - How to reset the server. - - C(software) is a software reset. This should be similar to pressing Ctrl+Alt+Del on the keyboard. - - C(power) is a hardware reset similar to pressing the Power button. An ACPI signal is sent, and if the + - V(software) is a software reset. This should be similar to pressing Ctrl+Alt+Del on the keyboard. + - V(power) is a hardware reset similar to pressing the Power button. An ACPI signal is sent, and if the server is configured correctly, this will trigger a regular shutdown. - - C(hardware) is a hardware reset similar to pressing the Restart button. The power is cycled for the server. - - C(manual) is a manual reset. This requests a technician to manually do the shutdown while looking at the + - V(hardware) is a hardware reset similar to pressing the Restart button. The power is cycled for the server. + - V(manual) is a manual reset. This requests a technician to manually do the shutdown while looking at the screen output. B(Be careful) and only use this when really necessary! - Note that not every server supports every reset method! type: str diff --git a/ansible_collections/community/hrobot/plugins/modules/reverse_dns.py b/ansible_collections/community/hrobot/plugins/modules/reverse_dns.py index 200489217..f3a914679 100644 --- a/ansible_collections/community/hrobot/plugins/modules/reverse_dns.py +++ b/ansible_collections/community/hrobot/plugins/modules/reverse_dns.py @@ -44,7 +44,7 @@ options: required: true state: description: - - Whether to set or update (C(present)) or delete (C(absent)) the reverse DNS entry for I(ip). + - Whether to set or update (V(present)) or delete (V(absent)) the reverse DNS entry for O(ip). type: str default: present choices: @@ -52,8 +52,8 @@ options: - absent value: description: - - The reverse DNS entry for I(ip). - - Required if I(state=present). + - The reverse DNS entry for O(ip). + - Required if O(state=present). type: str ''' diff --git a/ansible_collections/community/hrobot/plugins/modules/server.py b/ansible_collections/community/hrobot/plugins/modules/server.py index 2a24986e3..d32320af6 100644 --- a/ansible_collections/community/hrobot/plugins/modules/server.py +++ b/ansible_collections/community/hrobot/plugins/modules/server.py @@ -100,7 +100,7 @@ server: traffic: description: - Free traffic quota. - - C(unlimited) in case of unlimited traffic. + - V(unlimited) in case of unlimited traffic. type: str sample: 5 TB returned: success diff --git a/ansible_collections/community/hrobot/plugins/modules/server_info.py b/ansible_collections/community/hrobot/plugins/modules/server_info.py index b3f6da11d..eed9f2289 100644 --- a/ansible_collections/community/hrobot/plugins/modules/server_info.py +++ b/ansible_collections/community/hrobot/plugins/modules/server_info.py @@ -40,9 +40,9 @@ options: full_info: description: - Whether to provide full information for every server. - - Setting this to C(true) requires one REST call per server, + - Setting this to V(true) requires one REST call per server, which is slow and reduces your rate limit. Use with care. - - When I(server_number) is specified, this option is set to C(true). + - When O(server_number) is specified, this option is set to V(true). type: bool default: false ''' @@ -113,7 +113,7 @@ servers: traffic: description: - Free traffic quota. - - C(unlimited) in case of unlimited traffic. + - V(unlimited) in case of unlimited traffic. type: str sample: 5 TB returned: success @@ -171,55 +171,55 @@ servers: - Whether the server can be automatically reset. type: bool sample: true - returned: when I(full_info=true) + returned: when O(full_info=true) rescue: description: - Whether the rescue system is available. type: bool sample: false - returned: when I(full_info=true) + returned: when O(full_info=true) vnc: description: - Flag of VNC installation availability. type: bool sample: true - returned: when I(full_info=true) + returned: when O(full_info=true) windows: description: - Flag of Windows installation availability. type: bool sample: true - returned: when I(full_info=true) + returned: when O(full_info=true) plesk: description: - Flag of Plesk installation availability. type: bool sample: true - returned: when I(full_info=true) + returned: when O(full_info=true) cpanel: description: - Flag of cPanel installation availability. type: bool sample: true - returned: when I(full_info=true) + returned: when O(full_info=true) wol: description: - Flag of Wake On Lan availability. type: bool sample: true - returned: when I(full_info=true) + returned: when O(full_info=true) hot_swap: description: - Flag of Hot Swap availability. type: bool sample: true - returned: when I(full_info=true) + returned: when O(full_info=true) linked_storagebox: description: - Linked Storage Box ID. type: int sample: 12345 - returned: when I(full_info=true) + returned: when O(full_info=true) ''' from ansible.module_utils.basic import AnsibleModule diff --git a/ansible_collections/community/hrobot/plugins/modules/ssh_key.py b/ansible_collections/community/hrobot/plugins/modules/ssh_key.py index 2353514b9..e2064592c 100644 --- a/ansible_collections/community/hrobot/plugins/modules/ssh_key.py +++ b/ansible_collections/community/hrobot/plugins/modules/ssh_key.py @@ -38,9 +38,9 @@ options: state: description: - Whether to make sure a public SSH key is present or absent. - - C(present) makes sure that the SSH key is available, and - potentially updates names for existing SHS public keys. - - C(absent) makes sure that the SSH key is not available. + - V(present) makes sure that the SSH key is available, and + potentially updates names for existing SSH public keys. + - V(absent) makes sure that the SSH key is not available. The fingerprint or public key data is used for matching the key. required: true @@ -51,19 +51,19 @@ options: name: description: - The public key's name. - - Required if I(state=present), and ignored if I(state=absent). + - Required if O(state=present), and ignored if O(state=absent). type: str fingerprint: description: - The MD5 fingerprint of the public SSH key to remove. - - One of I(public_key) and I(fingerprint) are required if I(state=absent). + - One of O(public_key) and O(fingerprint) are required if O(state=absent). type: str public_key: description: - The public key data in OpenSSH format. - - "Example: C(ssh-rsa AAAAB3NzaC1yc+...)" - - One of I(public_key) and I(fingerprint) are required if I(state=absent). - - Required if I(state=present). + - "Example: V(ssh-rsa AAAAB3NzaC1yc+...)" + - One of O(public_key) and O(fingerprint) are required if O(state=absent). + - Required if O(state=present). type: str ''' diff --git a/ansible_collections/community/hrobot/plugins/modules/v_switch.py b/ansible_collections/community/hrobot/plugins/modules/v_switch.py index 6035392a4..f4ab27a11 100644 --- a/ansible_collections/community/hrobot/plugins/modules/v_switch.py +++ b/ansible_collections/community/hrobot/plugins/modules/v_switch.py @@ -51,9 +51,9 @@ options: state: description: - State of the vSwitch. - - vSwitch is created if state is C(present), and deleted if state is C(absent). - - C(absent) just cancels the vSwitch at the end of the current day. - - When cancelling, you have to specify I(servers=[]) if you want to actively remove the servers in the vSwitch. + - vSwitch is created if state is V(present), and deleted if state is V(absent). + - V(absent) just cancels the vSwitch at the end of the current day. + - When cancelling, you have to specify O(servers=[]) if you want to actively remove the servers in the vSwitch. type: str default: present choices: [ present, absent ] diff --git a/ansible_collections/community/hrobot/tests/sanity/extra/extra-docs.json b/ansible_collections/community/hrobot/tests/sanity/extra/extra-docs.json index c2e612e5f..9a28d174f 100644 --- a/ansible_collections/community/hrobot/tests/sanity/extra/extra-docs.json +++ b/ansible_collections/community/hrobot/tests/sanity/extra/extra-docs.json @@ -1,10 +1,13 @@ { "include_symlinks": false, "prefixes": [ - "docs/docsite/" + "docs/docsite/", + "plugins/", + "roles/" ], "output": "path-line-column-message", "requirements": [ + "ansible-core", "antsibull-docs" ] } diff --git a/ansible_collections/community/hrobot/tests/sanity/extra/extra-docs.py b/ansible_collections/community/hrobot/tests/sanity/extra/extra-docs.py index 673104923..251e6d70f 100755 --- a/ansible_collections/community/hrobot/tests/sanity/extra/extra-docs.py +++ b/ansible_collections/community/hrobot/tests/sanity/extra/extra-docs.py @@ -13,9 +13,14 @@ import subprocess def main(): """Main entry point.""" - if not os.path.isdir(os.path.join('docs', 'docsite')): - return - p = subprocess.run(['antsibull-docs', 'lint-collection-docs', '.'], check=False) + env = os.environ.copy() + suffix = ':{env}'.format(env=env["ANSIBLE_COLLECTIONS_PATH"]) if 'ANSIBLE_COLLECTIONS_PATH' in env else '' + env['ANSIBLE_COLLECTIONS_PATH'] = '{root}{suffix}'.format(root=os.path.dirname(os.path.dirname(os.path.dirname(os.getcwd()))), suffix=suffix) + p = subprocess.run( + ['antsibull-docs', 'lint-collection-docs', '--plugin-docs', '--skip-rstcheck', '.'], + env=env, + check=False, + ) if p.returncode not in (0, 3): print('{0}:0:0: unexpected return code {1}'.format(sys.argv[0], p.returncode)) diff --git a/ansible_collections/community/hrobot/tests/sanity/ignore-2.16.txt b/ansible_collections/community/hrobot/tests/sanity/ignore-2.16.txt new file mode 100644 index 000000000..0d9329fad --- /dev/null +++ b/ansible_collections/community/hrobot/tests/sanity/ignore-2.16.txt @@ -0,0 +1 @@ +tests/ee/roles/smoke/library/smoke_ipaddress.py shebang diff --git a/ansible_collections/community/hrobot/tests/sanity/ignore-2.16.txt.license b/ansible_collections/community/hrobot/tests/sanity/ignore-2.16.txt.license new file mode 100644 index 000000000..edff8c768 --- /dev/null +++ b/ansible_collections/community/hrobot/tests/sanity/ignore-2.16.txt.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/ansible_collections/community/hrobot/tests/sanity/ignore-2.17.txt b/ansible_collections/community/hrobot/tests/sanity/ignore-2.17.txt new file mode 100644 index 000000000..0d9329fad --- /dev/null +++ b/ansible_collections/community/hrobot/tests/sanity/ignore-2.17.txt @@ -0,0 +1 @@ +tests/ee/roles/smoke/library/smoke_ipaddress.py shebang diff --git a/ansible_collections/community/hrobot/tests/sanity/ignore-2.17.txt.license b/ansible_collections/community/hrobot/tests/sanity/ignore-2.17.txt.license new file mode 100644 index 000000000..edff8c768 --- /dev/null +++ b/ansible_collections/community/hrobot/tests/sanity/ignore-2.17.txt.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/ansible_collections/community/hrobot/tests/unit/plugins/inventory/test_robot.py b/ansible_collections/community/hrobot/tests/unit/plugins/inventory/test_robot.py index 31d6adae0..d5514aee5 100644 --- a/ansible_collections/community/hrobot/tests/unit/plugins/inventory/test_robot.py +++ b/ansible_collections/community/hrobot/tests/unit/plugins/inventory/test_robot.py @@ -17,6 +17,7 @@ from ansible.inventory.data import InventoryData from ansible.inventory.manager import InventoryManager from ansible.module_utils.common.text.converters import to_native from ansible.template import Templar +from ansible.utils.unsafe_proxy import AnsibleUnsafe from ansible_collections.community.internal_test_tools.tests.unit.mock.path import mock_unfrackpath_noop from ansible_collections.community.internal_test_tools.tests.unit.mock.loader import DictDataLoader @@ -60,7 +61,7 @@ def inventory(): def get_option(option): - if option == 'filters': + if option == 'simple_filters': return {} if option == 'hetzner_user': return 'test' @@ -159,7 +160,7 @@ def test_inventory_file_simple(mocker): plugin: community.hrobot.robot hetzner_user: test hetzner_password: hunter2 - filters: + simple_filters: dc: foo """)} im = InventoryManager(loader=DictDataLoader(inventory_file), sources=inventory_filename) @@ -216,7 +217,7 @@ def test_inventory_file_simple_2(mocker): plugin: community.hrobot.robot hetzner_user: '{{ "test" }}' hetzner_password: '{{ "hunter2" }}' - filters: + simple_filters: dc: foo """)} im = InventoryManager(loader=DictDataLoader(inventory_file), sources=inventory_filename) @@ -260,7 +261,7 @@ def test_inventory_file_fail(mocker, error_result): plugin: community.hrobot.robot hetzner_user: test hetzner_password: hunter2 - filters: + simple_filters: dc: foo """)} im = InventoryManager(loader=DictDataLoader(inventory_file), sources=inventory_filename) @@ -359,3 +360,56 @@ def test_inventory_file_collision(mocker): assert len(im._inventory.groups['ungrouped'].hosts) == 1 assert len(im._inventory.groups['all'].hosts) == 0 # TODO: check for warning + + +def test_unsafe(inventory, mocker): + open_url = OpenUrlProxy([ + OpenUrlCall('GET', 200) + .result_json([ + { + 'server': { + 'server_ip': '1.2.3.4', + 'dc': 'abc', + }, + }, + { + 'server': { + 'server_ip': '1.2.3.5', + 'server_name': 'foo', + 'dc': 'EVALU{{ "" }}ATED', + }, + }, + ]) + .expect_url('{0}/server'.format(BASE_URL)), + ]) + mocker.patch('ansible_collections.community.hrobot.plugins.module_utils.robot.open_url', open_url) + + inventory.get_option = mocker.MagicMock(side_effect=get_option) + inventory.populate(inventory.get_servers()) + + open_url.assert_is_done() + + host_1 = inventory.inventory.get_host('1.2.3.4') + host_2 = inventory.inventory.get_host('foo') + + host_1_vars = host_1.get_vars() + host_2_vars = host_2.get_vars() + + assert host_1_vars['ansible_host'] == '1.2.3.4' + assert host_1_vars['hrobot_server_ip'] == '1.2.3.4' + assert host_1_vars['hrobot_dc'] == 'abc' + + assert host_2_vars['ansible_host'] == '1.2.3.5' + assert host_2_vars['hrobot_server_ip'] == '1.2.3.5' + assert host_2_vars['hrobot_server_name'] == 'foo' + assert host_2_vars['hrobot_dc'] == 'EVALU{{ "" }}ATED' + + # Make sure everything is unsafe + assert isinstance(host_1_vars['ansible_host'], AnsibleUnsafe) + assert isinstance(host_1_vars['hrobot_server_ip'], AnsibleUnsafe) + assert isinstance(host_1_vars['hrobot_dc'], AnsibleUnsafe) + + assert isinstance(host_2_vars['ansible_host'], AnsibleUnsafe) + assert isinstance(host_2_vars['hrobot_server_ip'], AnsibleUnsafe) + assert isinstance(host_2_vars['hrobot_server_name'], AnsibleUnsafe) + assert isinstance(host_2_vars['hrobot_dc'], AnsibleUnsafe) diff --git a/ansible_collections/community/hrobot/tests/unit/plugins/module_utils/test_failover.py b/ansible_collections/community/hrobot/tests/unit/plugins/module_utils/test_failover.py index 56cd02944..dc1a3911d 100644 --- a/ansible_collections/community/hrobot/tests/unit/plugins/module_utils/test_failover.py +++ b/ansible_collections/community/hrobot/tests/unit/plugins/module_utils/test_failover.py @@ -67,14 +67,22 @@ GET_FAILOVER_FAIL = [ ), )).encode('utf-8'), )), - 'Request failed: 400 foo (bar)' + 'Request failed: 400 foo (bar)', + { + 'error': { + 'code': 'foo', + 'status': 400, + 'message': 'bar', + }, + }, ), ( '1.2.3.4', (None, dict( body='{"foo": "bar"}'.encode('utf-8'), )), - 'Cannot interpret result: {"foo": "bar"}' + 'Cannot interpret result: {"foo": "bar"}', + {}, ), ] @@ -87,16 +95,16 @@ def test_get_failover_record(monkeypatch, ip, return_value, result, record): assert failover.get_failover_record(module, ip) == record -@pytest.mark.parametrize("ip, return_value, result", GET_FAILOVER_FAIL) -def test_get_failover_record_fail(monkeypatch, ip, return_value, result): +@pytest.mark.parametrize("ip, return_value, fail_msg, fail_kwargs", GET_FAILOVER_FAIL) +def test_get_failover_record_fail(monkeypatch, ip, return_value, fail_msg, fail_kwargs): module = get_module_mock() robot.fetch_url = MagicMock(return_value=copy.deepcopy(return_value)) with pytest.raises(ModuleFailException) as exc: failover.get_failover_record(module, ip) - assert exc.value.fail_msg == result - assert exc.value.fail_kwargs == dict() + assert exc.value.fail_msg == fail_msg + assert exc.value.fail_kwargs == fail_kwargs @pytest.mark.parametrize("ip, return_value, result, record", GET_FAILOVER_SUCCESS) @@ -107,16 +115,16 @@ def test_get_failover(monkeypatch, ip, return_value, result, record): assert failover.get_failover(module, ip) == result -@pytest.mark.parametrize("ip, return_value, result", GET_FAILOVER_FAIL) -def test_get_failover_fail(monkeypatch, ip, return_value, result): +@pytest.mark.parametrize("ip, return_value, fail_msg, fail_kwargs", GET_FAILOVER_FAIL) +def test_get_failover_fail(monkeypatch, ip, return_value, fail_msg, fail_kwargs): module = get_module_mock() robot.fetch_url = MagicMock(return_value=copy.deepcopy(return_value)) with pytest.raises(ModuleFailException) as exc: failover.get_failover(module, ip) - assert exc.value.fail_msg == result - assert exc.value.fail_kwargs == dict() + assert exc.value.fail_msg == fail_msg + assert exc.value.fail_kwargs == fail_kwargs # ######################################################################################## @@ -164,7 +172,14 @@ SET_FAILOVER_FAIL = [ ), )).encode('utf-8'), )), - 'Request failed: 400 foo (bar)' + 'Request failed: 400 foo (bar)', + { + 'error': { + 'code': 'foo', + 'status': 400, + 'message': 'bar', + }, + }, ), ] @@ -177,13 +192,13 @@ def test_set_failover(monkeypatch, ip, value, return_value, result): assert failover.set_failover(module, ip, value) == result -@pytest.mark.parametrize("ip, value, return_value, result", SET_FAILOVER_FAIL) -def test_set_failover_fail(monkeypatch, ip, value, return_value, result): +@pytest.mark.parametrize("ip, value, return_value, fail_msg, fail_kwargs", SET_FAILOVER_FAIL) +def test_set_failover_fail(monkeypatch, ip, value, return_value, fail_msg, fail_kwargs): module = get_module_mock() robot.fetch_url = MagicMock(return_value=copy.deepcopy(return_value)) with pytest.raises(ModuleFailException) as exc: failover.set_failover(module, ip, value) - assert exc.value.fail_msg == result - assert exc.value.fail_kwargs == dict() + assert exc.value.fail_msg == fail_msg + assert exc.value.fail_kwargs == fail_kwargs diff --git a/ansible_collections/community/hrobot/tests/unit/plugins/module_utils/test_robot.py b/ansible_collections/community/hrobot/tests/unit/plugins/module_utils/test_robot.py index b53049e8b..8f5c5cd67 100644 --- a/ansible_collections/community/hrobot/tests/unit/plugins/module_utils/test_robot.py +++ b/ansible_collections/community/hrobot/tests/unit/plugins/module_utils/test_robot.py @@ -80,7 +80,14 @@ FETCH_URL_JSON_FAIL = [ )).encode('utf-8'), )), None, - 'Request failed: 400 foo (bar)' + 'Request failed: 400 foo (bar)', + { + 'error': { + 'code': "foo", + 'status': 400, + 'message': "bar", + }, + }, ), ( (None, dict( @@ -89,21 +96,67 @@ FETCH_URL_JSON_FAIL = [ code="foo", status=400, message="bar", + missing=None, + invalid=None, + max_request=None, + interval=None, ), )).encode('utf-8'), )), ['bar'], - 'Request failed: 400 foo (bar)' + 'Request failed: 400 foo (bar)', + { + 'error': { + 'code': "foo", + 'status': 400, + 'message': "bar", + 'missing': None, + 'invalid': None, + 'max_request': None, + 'interval': None, + }, + }, + ), + ( + (None, dict( + body=json.dumps(dict( + error=dict( + code="foo", + status=400, + message="bar", + missing=["foo"], + invalid=["bar"], + max_request=0, + interval=0, + ), + )).encode('utf-8'), + )), + None, + "Request failed: 400 foo (bar). Missing input parameters: ['foo']. Invalid input" + " parameters: ['bar']. Maximum allowed requests: 0. Time interval in seconds: 0", + { + 'error': { + 'code': "foo", + 'status': 400, + 'message': "bar", + 'missing': ["foo"], + 'invalid': ["bar"], + 'max_request': 0, + 'interval': 0, + }, + }, ), ( (None, dict(body='{this is not json}'.encode('utf-8'))), [], - 'Cannot decode content retrieved from https://foo/bar' + 'Cannot decode content retrieved from https://foo/bar', + {}, ), ( (None, dict(status=400)), [], - 'Cannot retrieve content from https://foo/bar, HTTP status code 400' + 'Cannot retrieve content from https://foo/bar, HTTP status code 400', + {}, ), ] @@ -116,16 +169,18 @@ def test_fetch_url_json(monkeypatch, return_value, accept_errors, result): assert robot.fetch_url_json(module, 'https://foo/bar', accept_errors=accept_errors) == result -@pytest.mark.parametrize("return_value, accept_errors, result", FETCH_URL_JSON_FAIL) -def test_fetch_url_json_fail(monkeypatch, return_value, accept_errors, result): +@pytest.mark.parametrize("return_value, accept_errors, fail_msg, fail_kwargs", FETCH_URL_JSON_FAIL) +def test_fetch_url_json_fail(monkeypatch, return_value, accept_errors, fail_msg, fail_kwargs): module = get_module_mock() robot.fetch_url = MagicMock(return_value=return_value) with pytest.raises(ModuleFailException) as exc: robot.fetch_url_json(module, 'https://foo/bar', accept_errors=accept_errors) - assert exc.value.fail_msg == result - assert exc.value.fail_kwargs == dict() + print(exc.value.fail_msg) + print(exc.value.fail_kwargs) + assert exc.value.fail_msg == fail_msg + assert exc.value.fail_kwargs == fail_kwargs def test_fetch_url_json_empty(monkeypatch): @@ -139,6 +194,8 @@ def test_fetch_url_json_empty(monkeypatch): with pytest.raises(ModuleFailException) as exc: robot.fetch_url_json(module, 'https://foo/bar', allow_empty_result=True) + print(exc.value.fail_msg) + print(exc.value.fail_kwargs) assert exc.value.fail_msg == 'Cannot retrieve content from https://foo/bar, HTTP status code 400' assert exc.value.fail_kwargs == dict() @@ -153,8 +210,8 @@ def test_plugin_open_url_json(monkeypatch, return_value, accept_errors, result): assert robot.plugin_open_url_json(plugin, 'https://foo/bar', accept_errors=accept_errors) == result -@pytest.mark.parametrize("return_value, accept_errors, result", FETCH_URL_JSON_FAIL) -def test_plugin_open_url_json_fail(monkeypatch, return_value, accept_errors, result): +@pytest.mark.parametrize("return_value, accept_errors, fail_msg, fail_kwargs", FETCH_URL_JSON_FAIL) +def test_plugin_open_url_json_fail(monkeypatch, return_value, accept_errors, fail_msg, fail_kwargs): response = MagicMock() response.read = MagicMock(return_value=return_value[1].get('body', '')) robot.open_url = MagicMock(side_effect=robot.HTTPError('https://foo/bar', 400, 'Error!', {}, response)) @@ -163,7 +220,8 @@ def test_plugin_open_url_json_fail(monkeypatch, return_value, accept_errors, res with pytest.raises(robot.PluginException) as exc: robot.plugin_open_url_json(plugin, 'https://foo/bar', accept_errors=accept_errors) - assert exc.value.error_message == result + print(exc.value.error_message) + assert exc.value.error_message == fail_msg def test_plugin_open_url_json_fail_other(monkeypatch): diff --git a/ansible_collections/community/hrobot/tests/requirements.yml b/ansible_collections/community/hrobot/tests/unit/requirements.yml index dde980c10..586a6a1b3 100644 --- a/ansible_collections/community/hrobot/tests/requirements.yml +++ b/ansible_collections/community/hrobot/tests/unit/requirements.yml @@ -3,5 +3,5 @@ # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) # SPDX-License-Identifier: GPL-3.0-or-later -unit_tests_dependencies: +collections: - community.internal_test_tools |