├── changelogs ├── fragments │ └── .keep └── config.yaml ├── tests ├── unit │ ├── requirements.txt │ └── plugins │ │ ├── test_inventory.py │ │ └── conftest.py └── integration │ ├── .gitignore │ ├── requirements.txt │ ├── targets │ ├── scaleway_registry_namespace │ │ ├── aliases │ │ ├── defaults │ │ │ └── main.yml │ │ └── tasks │ │ │ └── main.yml │ ├── .gitkeep │ ├── scaleway_vpc_private_network │ │ ├── defaults │ │ │ └── main.yml │ │ └── tasks │ │ │ └── main.yml │ └── scaleway_secret │ │ └── tasks │ │ └── main.yml │ └── integration_config.yml.template ├── requirements-scaleway.txt ├── .github ├── CODEOWNERS └── workflows │ ├── integration-nightly.yml │ ├── format.yml │ ├── lint.yml │ ├── ansible-lint.yml │ ├── dependabot.yml │ ├── ansible-test-sanity.yml │ ├── extra-docs-linting.yml │ ├── typing.yml │ ├── ansible-test-units.yml │ ├── ansible-test-integration.yml │ └── release.yml ├── codecov.yml ├── meta ├── execution-environment.yml └── runtime.yml ├── pyproject.toml ├── plugins ├── doc_fragments │ ├── scaleway_waitable_resource.py │ └── scaleway.py ├── module_utils │ ├── model.py │ └── scaleway_secret.py ├── lookup │ └── scaleway_secret.py └── modules │ ├── scaleway_vpcgw_ip.py │ ├── scaleway_instance_ip.py │ ├── scaleway_instance_private_nic.py │ ├── scaleway_domain_ssl_certificate.py │ ├── scaleway_lb_route.py │ ├── scaleway_vpcgw_dhcp_entry.py │ ├── scaleway_function_domain.py │ ├── scaleway_container_domain.py │ ├── scaleway_account_project.py │ ├── scaleway_iam_group.py │ ├── scaleway_rdb_read_replica.py │ ├── scaleway_iam_ssh_key.py │ ├── scaleway_iam_application.py │ ├── scaleway_iam_api_key.py │ ├── scaleway_rdb_endpoint.py │ ├── scaleway_function_token.py │ ├── scaleway_container_token.py │ ├── scaleway_vpcgw_pat_rule.py │ ├── scaleway_mnq_credential.py │ ├── scaleway_mnq_namespace.py │ ├── scaleway_iot_network.py │ ├── scaleway_rdb_snapshot.py │ ├── scaleway_lb_subscriber.py │ ├── scaleway_instance_placement_group.py │ └── scaleway_instance_volume.py ├── docs └── docsite │ └── links.yml ├── .gitignore ├── galaxy.yml ├── README.md └── CHANGELOG.rst /changelogs/fragments/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/unit/requirements.txt: -------------------------------------------------------------------------------- 1 | scaleway>=2.9.0 -------------------------------------------------------------------------------- /requirements-scaleway.txt: -------------------------------------------------------------------------------- 1 | scaleway>=2.9.0 2 | pyyaml 3 | -------------------------------------------------------------------------------- /tests/integration/.gitignore: -------------------------------------------------------------------------------- 1 | integration_config.yml 2 | -------------------------------------------------------------------------------- /tests/integration/requirements.txt: -------------------------------------------------------------------------------- 1 | scaleway>=2.9.0 2 | pyyaml -------------------------------------------------------------------------------- /tests/integration/targets/scaleway_registry_namespace/aliases: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Codeowners for scaleway/ansible 2 | 3 | * @remyleone 4 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | fixes: 2 | - "/ansible_collections/community/scaleway/::" 3 | -------------------------------------------------------------------------------- /meta/execution-environment.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | python: requirements-scaleway.txt 4 | version: 1 5 | -------------------------------------------------------------------------------- /tests/integration/targets/.gitkeep: -------------------------------------------------------------------------------- 1 | This is a placeholder file that only exists to keep the current 2 | directory in Git. It is safe to remove it once this directory contains 3 | the actual test files. 4 | -------------------------------------------------------------------------------- /tests/integration/integration_config.yml.template: -------------------------------------------------------------------------------- 1 | --- 2 | scw_access_key: ${SCW_ACCESS_KEY} 3 | scw_secret_key: ${SCW_SECRET_KEY} 4 | scw_default_project_id: ${SCW_DEFAULT_PROJECT_ID} 5 | scw_default_region: ${SCW_DEFAULT_REGION} 6 | -------------------------------------------------------------------------------- /tests/integration/targets/scaleway_vpc_private_network/defaults/main.yml: -------------------------------------------------------------------------------- 1 | resource_name: "ansible-test-private-network" 2 | resource_region: "fr-par" 3 | resource_tags: 4 | - "tag1" 5 | - "tag2" 6 | resource_subnets: 7 | - "1.234.56.78/9" 8 | -------------------------------------------------------------------------------- /tests/integration/targets/scaleway_registry_namespace/defaults/main.yml: -------------------------------------------------------------------------------- 1 | resource_name: "ansible-test-registry" 2 | resource_description: "Ansible Scaleway Registry Namespace integration tests" 3 | resource_is_public: false 4 | resource_region: "fr-par" 5 | -------------------------------------------------------------------------------- /.github/workflows/integration-nightly.yml: -------------------------------------------------------------------------------- 1 | name: Integration Nightly 2 | 3 | on: 4 | schedule: 5 | - cron: "0 0 * * *" 6 | 7 | jobs: 8 | integration: 9 | uses: ./.github/workflows/ansible-test-integration.yml 10 | secrets: inherit 11 | -------------------------------------------------------------------------------- /.github/workflows/format.yml: -------------------------------------------------------------------------------- 1 | name: Format 2 | 3 | permissions: 4 | contents: read 5 | 6 | on: 7 | pull_request: 8 | 9 | jobs: 10 | ruff: 11 | name: Format 12 | runs-on: ubuntu-24.04 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: astral-sh/ruff-action@v2 16 | with: 17 | args: "format --check" 18 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Check linters 2 | 3 | permissions: 4 | contents: read 5 | 6 | on: 7 | push: 8 | branches: 9 | - main 10 | pull_request: 11 | merge_group: 12 | 13 | jobs: 14 | ruff: 15 | name: Ruff 16 | runs-on: ubuntu-24.04 17 | steps: 18 | - uses: actions/checkout@v4 19 | - uses: astral-sh/ruff-action@v2 20 | -------------------------------------------------------------------------------- /.github/workflows/ansible-lint.yml: -------------------------------------------------------------------------------- 1 | name: ansible-lint 2 | on: 3 | pull_request: 4 | jobs: 5 | build: 6 | name: Ansible Lint # Naming the build is important to use it as a status check 7 | runs-on: ubuntu-24.04 8 | steps: 9 | - uses: actions/checkout@v4 10 | - name: Run ansible-lint 11 | uses: ansible/ansible-lint@main 12 | # optional (see below): 13 | with: 14 | args: "--exclude=.github" 15 | setup_python: "true" 16 | working_directory: "" 17 | requirements_file: "" 18 | -------------------------------------------------------------------------------- /.github/workflows/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: github-actions 9 | directory: / 10 | schedule: 11 | interval: monthly 12 | 13 | - package-ecosystem: pip 14 | directory: / 15 | schedule: 16 | interval: monthly 17 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "ansible" 3 | version = "2.7.0" 4 | requires-python = ">=3.8" 5 | 6 | [tool.poetry] 7 | package-mode = false 8 | 9 | [tool.poetry.group.dev.dependencies] 10 | ty = "^0.0.1a15" 11 | pyrefly = "^0.24.2" 12 | ruff = "^0.12.4" 13 | 14 | [tool.ruff.lint] 15 | ignore = ["E402"] 16 | 17 | [tool.ty.rules] 18 | unresolved-import = "ignore" 19 | unresolved-attribute = "ignore" 20 | possibly-unbound-attribute = "ignore" 21 | no-matching-overload = "ignore" 22 | invalid-argument-type = "ignore" 23 | invalid-return-type = "ignore" 24 | 25 | [tool.pyrefly.errors] 26 | import-error = false 27 | missing-attribute = false 28 | bad-assignment = false 29 | no-matching-overload = false 30 | bad-override = false 31 | bad-argument-type = false 32 | bad-return = false 33 | -------------------------------------------------------------------------------- /changelogs/config.yaml: -------------------------------------------------------------------------------- 1 | changelog_filename_template: ../CHANGELOG.rst 2 | changelog_filename_version_depth: 0 3 | changes_file: changelog.yaml 4 | changes_format: combined 5 | keep_fragments: false 6 | mention_ancestor: true 7 | new_plugins_after_name: removed_features 8 | notesdir: fragments 9 | prelude_section_name: release_summary 10 | prelude_section_title: Release Summary 11 | sections: 12 | - - major_changes 13 | - Major Changes 14 | - - minor_changes 15 | - Minor Changes 16 | - - breaking_changes 17 | - Breaking Changes / Porting Guide 18 | - - deprecated_features 19 | - Deprecated Features 20 | - - removed_features 21 | - Removed Features (previously deprecated) 22 | - - security_fixes 23 | - Security Fixes 24 | - - bugfixes 25 | - Bugfixes 26 | - - known_issues 27 | - Known Issues 28 | title: Community Scaleway 29 | trivial_section_name: trivial 30 | -------------------------------------------------------------------------------- /.github/workflows/ansible-test-sanity.yml: -------------------------------------------------------------------------------- 1 | # We only support ansible-core versions that are not EOL 2 | # https://docs.ansible.com/ansible/latest/reference_appendices/release_and_maintenance.html 3 | 4 | name: Sanity 5 | 6 | on: 7 | pull_request: 8 | push: 9 | branches: 10 | - main 11 | workflow_dispatch: 12 | 13 | jobs: 14 | sanity: 15 | timeout-minutes: 30 16 | name: Sanity (Ⓐ$${{ matrix.ansible }}) 17 | strategy: 18 | matrix: 19 | ansible: 20 | - stable-2.19 21 | - stable-2.17 22 | - stable-2.18 23 | runs-on: ubuntu-latest 24 | steps: 25 | - name: Perform testing 26 | uses: ansible-community/ansible-test-gh-action@release/v1 27 | with: 28 | ansible-core-version: ${{ matrix.ansible }} 29 | origin-python-version: 3.11 30 | target-python-version: 3.11 31 | testing-type: sanity 32 | -------------------------------------------------------------------------------- /plugins/doc_fragments/scaleway_waitable_resource.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Copyright: (c), Ansible Project 4 | # Copyright: (c), Guillaume MARTINEZ 5 | # Copyright: (c), Nathanael Demacon (@quantumsheep) 6 | # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) 7 | # SPDX-License-Identifier: GPL-3.0-or-later 8 | 9 | from __future__ import absolute_import, division, print_function 10 | 11 | __metaclass__ = type 12 | 13 | 14 | class ModuleDocFragment(object): 15 | # Standard documentation fragment 16 | DOCUMENTATION = r""" 17 | options: 18 | wait: 19 | description: 20 | - Wait for the resource to reach its desired state before returning. 21 | type: bool 22 | default: true 23 | wait_timeout: 24 | type: int 25 | description: 26 | - Time to wait for the resource to reach the expected state. 27 | required: false 28 | default: 300 29 | """ 30 | -------------------------------------------------------------------------------- /.github/workflows/extra-docs-linting.yml: -------------------------------------------------------------------------------- 1 | name: Lint extra docsite docs and links 2 | on: 3 | # Run CI against all pushes (direct commits, also merged PRs), Pull Requests 4 | push: 5 | branches: 6 | - main 7 | - stable-* 8 | pull_request: 9 | # Run CI once per day (at 06:00 UTC) 10 | # This ensures that even if there haven't been commits that we are still testing against latest version of ansible-test for each ansible-base version 11 | schedule: 12 | - cron: '0 6 * * *' 13 | 14 | jobs: 15 | docsite: 16 | name: Lint extra docsite docs and links 17 | permissions: 18 | contents: read 19 | runs-on: ubuntu-latest 20 | steps: 21 | 22 | - name: Check out code 23 | uses: actions/checkout@v3 24 | 25 | - name: Set up Python 26 | uses: actions/setup-python@v3 27 | with: 28 | python-version: '3.10' 29 | 30 | - name: Install antsibull-docs 31 | run: pip install antsibull-docs --disable-pip-version-check 32 | 33 | - name: Run collection docs linter 34 | run: antsibull-docs lint-collection-docs . 35 | -------------------------------------------------------------------------------- /.github/workflows/typing.yml: -------------------------------------------------------------------------------- 1 | name: Check type hinting 2 | 3 | permissions: 4 | contents: read 5 | 6 | on: 7 | push: 8 | branches: 9 | - main 10 | pull_request: 11 | merge_group: 12 | 13 | jobs: 14 | ty: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | - name: Install poetry 19 | run: pipx install poetry 20 | - name: Set up Python 21 | uses: actions/setup-python@v5 22 | with: 23 | python-version: "3.13" 24 | cache: "poetry" 25 | - name: Install dependencies and library 26 | run: poetry install 27 | - name: Check typing 28 | run: poetry run ty check 29 | 30 | pyrefly: 31 | runs-on: ubuntu-latest 32 | steps: 33 | - uses: actions/checkout@v4 34 | - name: Install poetry 35 | run: pipx install poetry 36 | - name: Set up Python 37 | uses: actions/setup-python@v5 38 | with: 39 | python-version: "3.13" 40 | cache: "poetry" 41 | - name: Install dependencies and library 42 | run: poetry install 43 | - name: Check typing with pyrefly 44 | run: poetry run pyrefly check 45 | -------------------------------------------------------------------------------- /.github/workflows/ansible-test-units.yml: -------------------------------------------------------------------------------- 1 | # We only support ansible-core versions that are not EOL 2 | # https://docs.ansible.com/ansible/latest/reference_appendices/release_and_maintenance.html 3 | 4 | name: units 5 | 6 | on: 7 | pull_request: 8 | push: 9 | branches: 10 | - main 11 | workflow_dispatch: 12 | 13 | jobs: 14 | units: 15 | timeout-minutes: 30 16 | name: Units (Ⓐ$${{ matrix.ansible-version }}) 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | ansible-version: 21 | - stable-2.19 22 | - stable-2.17 23 | - stable-2.18 24 | env: 25 | ansible-collections-path: "./ansible_collections/scaleway/scaleway" 26 | 27 | runs-on: ubuntu-latest 28 | steps: 29 | - name: Create directory 30 | run: | 31 | mkdir -p ${{ env.ansible-collections-path }} 32 | 33 | - name: Checkout the repo 34 | uses: actions/checkout@v4 35 | with: 36 | path: ${{ env.ansible-collections-path }} 37 | 38 | - name: Setup Python and install ansible 39 | uses: actions/setup-python@v5 40 | with: 41 | python-version: 3.11 42 | 43 | - name: Install ansible 44 | run: | 45 | python -m pip install \ 46 | https://github.com/ansible/ansible/archive/${{ matrix.ansible-version }}.tar.gz \ 47 | --disable-pip-version-check 48 | 49 | - name: Run unit tests with ansible ${{ matrix.ansible-version }} 50 | working-directory: ${{ env.ansible-collections-path }} 51 | run: | 52 | ansible-test units -v --requirements 53 | -------------------------------------------------------------------------------- /plugins/doc_fragments/scaleway.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Copyright: (c), Ansible Project 4 | # Copyright: (c), Nathanael Demacon (@quantumsheep) 5 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 6 | 7 | from __future__ import absolute_import, division, print_function 8 | 9 | __metaclass__ = type 10 | 11 | 12 | class ModuleDocFragment(object): 13 | # Standard documentation fragment 14 | DOCUMENTATION = r""" 15 | options: 16 | profile: 17 | description: 18 | - The Scaleway profile to load. Leave empty to disable. 19 | type: str 20 | required: false 21 | config_file: 22 | description: 23 | - Path to the Scaleway configuration file. Leave empty to use the default path. 24 | type: str 25 | required: false 26 | access_key: 27 | description: 28 | - Scaleway API access key. 29 | type: str 30 | required: false 31 | secret_key: 32 | description: 33 | - Scaleway API secret key. 34 | type: str 35 | required: false 36 | api_url: 37 | description: 38 | - Scaleway API URL. 39 | type: str 40 | default: https://api.scaleway.com 41 | project_id: 42 | description: 43 | - Scaleway project ID. 44 | type: str 45 | required: false 46 | organization_id: 47 | description: 48 | - Scaleway organization ID. 49 | type: str 50 | required: false 51 | api_allow_insecure: 52 | description: 53 | - Allow insecure connection to Scaleway API. 54 | type: bool 55 | default: false 56 | user_agent: 57 | description: 58 | - User agent used by the Scaleway API client. 59 | type: str 60 | """ 61 | -------------------------------------------------------------------------------- /tests/unit/plugins/test_inventory.py: -------------------------------------------------------------------------------- 1 | from ....plugins.inventory import scaleway as scaleway_inventory 2 | from ....plugins.inventory.scaleway import _Filters 3 | 4 | from unittest.mock import patch 5 | from scaleway.baremetal.v1.api import BaremetalV1API 6 | from scaleway import Client 7 | 8 | 9 | class TestInventory: 10 | @patch.object(BaremetalV1API, "list_servers_all") 11 | @patch.object(scaleway_inventory.InventoryModule, "_get_client") 12 | def test_get_elastic_metal( 13 | self, 14 | mocked_get_client, 15 | mocked_list_server_all, 16 | list_bare_metals, 17 | scaleway_config_profile, 18 | ): 19 | mocked_list_server_all.return_value = list_bare_metals 20 | inventory = scaleway_inventory.InventoryModule() 21 | mocked_client = Client.from_profile(scaleway_config_profile) 22 | 23 | instances = inventory._get_elastic_metal( 24 | mocked_client, _Filters(zones=["fr-par"]) 25 | ) 26 | mocked_list_server_all.assert_called_once_with(zone="fr-par", tags=None) 27 | assert len(instances) == 2 28 | assert instances[0].public_ipv4 == ["1.1.1.1", "192.168.0.1"] 29 | assert instances[0].public_ipv6 == [] 30 | assert instances[1].public_ipv4 == ["1.1.1.1"] 31 | assert instances[1].public_ipv6 == ["2001:db8::1"] 32 | 33 | def test_get_host_groups(self): 34 | inventory = scaleway_inventory.InventoryModule() 35 | host = scaleway_inventory._Host( 36 | id="123", 37 | tags=["tag1", "tag2", "some-tag", " white spaced-tag "], 38 | zone="fr-par", 39 | state="running", 40 | hostname="test", 41 | ) 42 | groups = inventory.get_host_groups(host) 43 | assert groups == {"tag1", "tag2", "fr_par", "some_tag", "white_spaced_tag"} 44 | -------------------------------------------------------------------------------- /.github/workflows/ansible-test-integration.yml: -------------------------------------------------------------------------------- 1 | name: Integration tests 2 | 3 | on: 4 | workflow_call: 5 | workflow_dispatch: 6 | pull_request: 7 | push: 8 | branches: 9 | - main 10 | 11 | jobs: 12 | integration: 13 | runs-on: ubuntu-latest 14 | timeout-minutes: 40 15 | strategy: 16 | fail-fast: false 17 | max-parallel: 1 18 | matrix: 19 | module: 20 | - scaleway_secret 21 | 22 | ansible-version: 23 | - stable-2.17 24 | - stable-2.18 25 | - stable-2.19 26 | env: 27 | ansible-collections-path: "./ansible_collections/scaleway/scaleway" 28 | 29 | steps: 30 | - name: Create directory 31 | run: | 32 | mkdir -p ${{ env.ansible-collections-path }} 33 | 34 | - name: Checkout the repo 35 | uses: actions/checkout@v4 36 | with: 37 | path: ${{ env.ansible-collections-path }} 38 | 39 | - name: Setup Python and install ansible 40 | uses: actions/setup-python@v5 41 | with: 42 | python-version: 3.11 43 | 44 | - name: Install ansible 45 | run: | 46 | python -m pip install \ 47 | https://github.com/ansible/ansible/archive/${{ matrix.ansible-version }}.tar.gz \ 48 | --disable-pip-version-check 49 | 50 | - name: Create scw config 51 | run: | 52 | mkdir -p $HOME/.config/scw 53 | cat << EOF > $HOME/.config/scw/config.yaml 54 | access_key: ${{ secrets.SCW_ACCESS_KEY }} 55 | secret_key: ${{ secrets.SCW_SECRET_KEY }} 56 | default_region: ${{ secrets.SCW_DEFAULT_REGION }} 57 | default_project_id: ${{ secrets.SCW_DEFAULT_PROJECT_ID }} 58 | EOF 59 | 60 | - name: Run integration tests with ansible ${{ matrix.ansible-version }} 61 | working-directory: ${{ env.ansible-collections-path }} 62 | run: | 63 | ansible-test integration -v --requirements ${{ matrix.module }} 64 | -------------------------------------------------------------------------------- /docs/docsite/links.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # This will make sure that plugin and module documentation gets Edit on GitHub links 3 | # that allow users to directly create a PR for this plugin or module in GitHub's UI. 4 | # Remove this section if the collection repository is not on GitHub, or if you do not want this 5 | # functionality for your collection. 6 | edit_on_github: 7 | repository: scaleway/ansible 8 | branch: main 9 | # If your collection root (the directory containing galaxy.yml) does not coincide with your 10 | # repository's root, you have to specify the path to the collection root here. For example, 11 | # if the collection root is in a subdirectory ansible_collections/community/scaleway 12 | # in your repository, you have to set path_prefix to 'ansible_collections/community/scaleway'. 13 | path_prefix: "" 14 | 15 | # Here you can add arbitrary extra links. Please keep the number of links down to a 16 | # minimum! Also please keep the description short, since this will be the text put on 17 | # a button. 18 | # 19 | # Also note that some links are automatically added from information in galaxy.yml. 20 | # The following are automatically added: 21 | # 1. A link to the issue tracker (if `issues` is specified); 22 | # 2. A link to the homepage (if `homepage` is specified and does not equal the 23 | # `documentation` or `repository` link); 24 | # 3. A link to the collection's repository (if `repository` is specified). 25 | 26 | extra_links: 27 | - description: Report an issue 28 | url: https://github.com/scaleway/ansible/issues/new/choose 29 | 30 | # Specify communication channels for your collection. We suggest to not specify more 31 | # than one place for communication per communication tool to avoid confusion. 32 | communication: 33 | matrix_rooms: 34 | - topic: General usage and support questions 35 | room: "#scaleway:ansible.im" 36 | irc_channels: 37 | - topic: General usage and support questions 38 | network: Libera 39 | channel: "#ansible-scaleway" 40 | -------------------------------------------------------------------------------- /meta/runtime.yml: -------------------------------------------------------------------------------- 1 | --- 2 | requires_ansible: ">=2.15.0" 3 | action_groups: 4 | all: 5 | - scaleway_account_project 6 | - scaleway_applesilicon_server 7 | - scaleway_baremetal_server 8 | - scaleway_container 9 | - scaleway_container_cron 10 | - scaleway_container_domain 11 | - scaleway_container_namespace 12 | - scaleway_container_token 13 | - scaleway_domain_ssl_certificate 14 | - scaleway_flexibleip_flexible_ip 15 | - scaleway_function 16 | - scaleway_function_cron 17 | - scaleway_function_domain 18 | - scaleway_function_namespace 19 | - scaleway_function_token 20 | - scaleway_function_trigger 21 | - scaleway_iam_api_key 22 | - scaleway_iam_application 23 | - scaleway_iam_group 24 | - scaleway_iam_policy 25 | - scaleway_iam_ssh_key 26 | - scaleway_instance_image 27 | - scaleway_instance_ip 28 | - scaleway_instance_placement_group 29 | - scaleway_instance_private_nic 30 | - scaleway_instance_security_group 31 | - scaleway_instance_security_group_rule 32 | - scaleway_instance_snapshot 33 | - scaleway_instance_volume 34 | - scaleway_iot_device 35 | - scaleway_iot_hub 36 | - scaleway_iot_network 37 | - scaleway_iot_route 38 | - scaleway_k8s_cluster 39 | - scaleway_k8s_pool 40 | - scaleway_lb 41 | - scaleway_lb_acl 42 | - scaleway_lb_backend 43 | - scaleway_lb_certificate 44 | - scaleway_lb_frontend 45 | - scaleway_lb_route 46 | - scaleway_lb_subscriber 47 | - scaleway_mnq_credential 48 | - scaleway_mnq_namespace 49 | - scaleway_rdb_database_backup 50 | - scaleway_rdb_endpoint 51 | - scaleway_rdb_instance 52 | - scaleway_rdb_read_replica 53 | - scaleway_rdb_snapshot 54 | - scaleway_redis_cluster 55 | - scaleway_registry_namespace 56 | - scaleway_secret 57 | - scaleway_vpc_private_network 58 | - scaleway_vpcgw_dhcp 59 | - scaleway_vpcgw_dhcp_entry 60 | - scaleway_vpcgw_gateway 61 | - scaleway_vpcgw_gateway_network 62 | - scaleway_vpcgw_ip 63 | - scaleway_vpcgw_pat_rule 64 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - "*" 7 | 8 | jobs: 9 | publish: 10 | name: Publish to Galaxy 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Check out code 14 | uses: actions/checkout@v3 15 | with: 16 | fetch-depth: 0 17 | 18 | - name: Set up Python 19 | uses: actions/setup-python@v4 20 | with: 21 | python-version: 3.8 22 | 23 | - name: Install Ansible 24 | run: pip install ansible 25 | 26 | - name: Install antsibull-changelog 27 | run: pip install antsibull-changelog 28 | 29 | - name: Check galaxy.yml version match the tag 30 | run: | 31 | VERSION=$(grep 'version:' galaxy.yml | awk '{print $2}') 32 | if [[ "$VERSION" != "${{ github.ref_name }}" ]]; then 33 | echo "galaxy.yml version does not match the tag: $VERSION != ${{ github.ref_name }}" 34 | exit 1 35 | fi 36 | 37 | - name: Build changelog 38 | run: antsibull-changelog release 39 | 40 | - name: Build collection 41 | run: ansible-galaxy collection build 42 | 43 | - name: Build and publish collection to Galaxy 44 | run: ansible-galaxy collection publish --api-key ${{ secrets.GALAXY_API_KEY }} scaleway-scaleway-${{ github.ref_name }}.tar.gz 45 | 46 | - name: Create a release with the collection artifact 47 | uses: softprops/action-gh-release@v1 48 | with: 49 | files: | 50 | scaleway-scaleway-${{ github.ref_name }}.tar.gz 51 | generate_release_notes: true 52 | 53 | - name: Create a PR to update changelog 54 | uses: peter-evans/create-pull-request@v4 55 | with: 56 | token: ${{ secrets.GITHUB_TOKEN }} 57 | commit-message: "docs: update changelog for ${{ github.ref_name }}" 58 | title: "docs: update changelog for ${{ github.ref_name }}" 59 | body: | 60 | Update changelog for ${{ github.ref_name }} 61 | branch: docs/update-changelog-${{ github.ref_name }} 62 | delete-branch: true 63 | base: main 64 | -------------------------------------------------------------------------------- /plugins/module_utils/model.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, division, print_function 2 | 3 | from dataclasses import asdict, dataclass, field 4 | from typing import Type, TypeVar 5 | 6 | 7 | T = TypeVar("T", bound="Model") 8 | 9 | 10 | @dataclass 11 | class Model: 12 | @classmethod 13 | def build_model(cls: Type[T], parameters: dict) -> T: 14 | model = cls( 15 | **{k: v for k, v in parameters.items() if k in cls.__dataclass_fields__} 16 | ) 17 | return model 18 | 19 | def diff(self, other: "Model") -> dict: 20 | """ 21 | diff two models guaranteed to be the same type 22 | the source model is the source of truth 23 | 24 | example: 25 | source: 26 | Secret( 27 | key1="value1", 28 | key2="value2", 29 | ) 30 | destination: 31 | Secret( 32 | key1="value1", 33 | key2="value2", 34 | ) 35 | return: 36 | {} 37 | 38 | source: 39 | Secret( 40 | key1="value1", 41 | key2="value2", 42 | ) 43 | destination: 44 | Secret( 45 | key1="value2", 46 | key2="value3", 47 | ) 48 | return: 49 | { 50 | "key1": "value1", 51 | "key2": "value2", 52 | } 53 | """ 54 | if self.__class__.__name__ != other.__class__.__name__: 55 | raise ValueError( 56 | f"The models are not the same: {self.__class__.__name__} != {other.__class__.__name__}" 57 | ) 58 | 59 | diff = {} 60 | 61 | self_as_dict = asdict(self) 62 | other_as_dict = asdict(other) 63 | 64 | for key, value in self_as_dict.items(): 65 | if other_as_dict[key] != value: 66 | diff[key] = value 67 | 68 | return diff 69 | 70 | 71 | @dataclass 72 | class Secret(Model): 73 | name: str 74 | id: str = "" 75 | description: str = "" 76 | tags: list[str] = field(default_factory=list) 77 | 78 | 79 | @dataclass 80 | class SecretVersion(Model): 81 | secret_id: str 82 | revision: str 83 | data: str = "" 84 | description: str = "" 85 | -------------------------------------------------------------------------------- /tests/integration/targets/scaleway_vpc_private_network/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Test VPC Private Network 3 | block: 4 | - name: Ensure Access Key is provided 5 | ansible.builtin.fail: 6 | msg: scw_access_key should be defined in tests/integration/integration_config.yml 7 | when: 8 | - scw_access_key is not defined 9 | - scw_access_key | length == 0 10 | 11 | - name: Ensure Secret Key is provided 12 | ansible.builtin.fail: 13 | msg: scw_secret_key should be defined in tests/integration/integration_config.yml 14 | when: 15 | - scw_secret_key is not defined 16 | - scw_secret_key | length == 0 17 | 18 | - name: Ensure Default Project ID is provided 19 | ansible.builtin.fail: 20 | msg: scw_default_project_id should be defined in tests/integration/integration_config.yml 21 | when: 22 | - scw_default_project_id is not defined 23 | - scw_default_project_id | length == 0 24 | 25 | - name: Create Private Network 26 | scaleway.scaleway.scaleway_vpc_private_network: 27 | name: "{{ resource_name }}" 28 | region: "{{ resource_region }}" 29 | project_id: "{{ scw_default_project_id }}" 30 | access_key: "{{ scw_access_key }}" 31 | secret_key: "{{ scw_secret_key }}" 32 | state: present 33 | tags: "{{ resource_tags }}" 34 | subnets: "{{ resource_subnets }}" 35 | register: integration_vpc_pn_creation 36 | 37 | - name: Delete Private Network 38 | scaleway.scaleway.scaleway_vpc_private_network: 39 | name: "{{ resource_name }}" 40 | region: "{{ resource_region }}" 41 | project_id: "{{ scw_default_project_id }}" 42 | access_key: "{{ scw_access_key }}" 43 | secret_key: "{{ scw_secret_key }}" 44 | state: absent 45 | tags: "{{ resource_tags }}" 46 | subnets: "{{ resource_subnets }}" 47 | register: integration_vpc_pn_deletion 48 | 49 | - name: Create Private Network (Check) 50 | check_mode: true 51 | scaleway.scaleway.scaleway_vpc_private_network: 52 | name: "{{ resource_name }}" 53 | region: "{{ resource_region }}" 54 | project_id: "{{ scw_default_project_id }}" 55 | access_key: "{{ scw_access_key }}" 56 | secret_key: "{{ scw_secret_key }}" 57 | state: present 58 | tags: "{{ resource_tags }}" 59 | subnets: "{{ resource_subnets }}" 60 | register: integration_vpc_pn_creation 61 | -------------------------------------------------------------------------------- /tests/integration/targets/scaleway_registry_namespace/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Test Registry namespace 3 | block: 4 | - name: Ensure Access Key is provided 5 | ansible.builtin.fail: 6 | msg: scw_access_key should be defined in tests/integration/integration_config.yml 7 | when: 8 | - scw_access_key is not defined 9 | - scw_access_key | length == 0 10 | 11 | - name: Ensure Secret Key is provided 12 | ansible.builtin.fail: 13 | msg: scw_secret_key should be defined in tests/integration/integration_config.yml 14 | when: 15 | - scw_secret_key is not defined 16 | - scw_secret_key | length == 0 17 | 18 | - name: Ensure Default Project ID is provided 19 | ansible.builtin.fail: 20 | msg: scw_default_project_id should be defined in tests/integration/integration_config.yml 21 | when: 22 | - scw_default_project_id is not defined 23 | - scw_default_project_id | length == 0 24 | 25 | - name: Create registry_namespace 26 | scaleway.scaleway.scaleway_registry_namespace: 27 | name: "{{ resource_name }}" 28 | region: "{{ resource_region }}" 29 | project_id: "{{ scw_default_project_id }}" 30 | access_key: "{{ scw_access_key }}" 31 | secret_key: "{{ scw_secret_key }}" 32 | state: present 33 | description: "{{ resource_description }}" 34 | is_public: "{{ resource_is_public }}" 35 | register: integration_registry_namespace_creation 36 | 37 | - name: Delete registry_namespace 38 | scaleway.scaleway.scaleway_registry_namespace: 39 | name: "{{ resource_name }}" 40 | region: "{{ resource_region }}" 41 | project_id: "{{ scw_default_project_id }}" 42 | access_key: "{{ scw_access_key }}" 43 | secret_key: "{{ scw_secret_key }}" 44 | state: absent 45 | description: "{{ resource_description }}" 46 | is_public: "{{ resource_is_public }}" 47 | register: integration_registry_namespace_deletion 48 | 49 | - name: Create a registry_namespace (Check) 50 | check_mode: true 51 | scaleway.scaleway.scaleway_registry_namespace: 52 | name: "{{ resource_name }}" 53 | region: "{{ resource_region }}" 54 | project_id: "{{ scw_default_project_id }}" 55 | access_key: "{{ scw_access_key }}" 56 | secret_key: "{{ scw_secret_key }}" 57 | state: present 58 | description: "{{ resource_description }}" 59 | is_public: "{{ resource_is_public }}" 60 | register: integration_registry_namespace_creation_check 61 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /tests/output/ 2 | /changelogs/.plugin-cache.yaml 3 | 4 | # Byte-compiled / optimized / DLL files 5 | __pycache__/ 6 | *.py[cod] 7 | *$py.class 8 | 9 | # C extensions 10 | *.so 11 | 12 | # Distribution / packaging 13 | .Python 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | downloads/ 18 | eggs/ 19 | .eggs/ 20 | lib/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | wheels/ 26 | pip-wheel-metadata/ 27 | share/python-wheels/ 28 | *.egg-info/ 29 | .installed.cfg 30 | *.egg 31 | MANIFEST 32 | 33 | # PyInstaller 34 | # Usually these files are written by a python script from a template 35 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 36 | *.manifest 37 | *.spec 38 | 39 | # Installer logs 40 | pip-log.txt 41 | pip-delete-this-directory.txt 42 | 43 | # Unit test / coverage reports 44 | htmlcov/ 45 | .tox/ 46 | .nox/ 47 | .coverage 48 | .coverage.* 49 | .cache 50 | nosetests.xml 51 | coverage.xml 52 | *.cover 53 | *.py,cover 54 | .hypothesis/ 55 | .pytest_cache/ 56 | 57 | # Translations 58 | *.mo 59 | *.pot 60 | 61 | # Django stuff: 62 | *.log 63 | local_settings.py 64 | db.sqlite3 65 | db.sqlite3-journal 66 | 67 | # Flask stuff: 68 | instance/ 69 | .webassets-cache 70 | 71 | # Scrapy stuff: 72 | .scrapy 73 | 74 | # Sphinx documentation 75 | docs/_build/ 76 | 77 | # PyBuilder 78 | target/ 79 | 80 | # Jupyter Notebook 81 | .ipynb_checkpoints 82 | 83 | # IPython 84 | profile_default/ 85 | ipython_config.py 86 | 87 | # pyenv 88 | .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 98 | __pypackages__/ 99 | 100 | # Celery stuff 101 | celerybeat-schedule 102 | celerybeat.pid 103 | 104 | # SageMath parsed files 105 | *.sage.py 106 | 107 | # Environments 108 | .env 109 | .venv 110 | env/ 111 | venv/ 112 | ENV/ 113 | env.bak/ 114 | venv.bak/ 115 | 116 | # Spyder project settings 117 | .spyderproject 118 | .spyproject 119 | 120 | # Rope project settings 121 | .ropeproject 122 | 123 | # mkdocs documentation 124 | /site 125 | 126 | # mypy 127 | .mypy_cache/ 128 | .dmypy.json 129 | dmypy.json 130 | 131 | # Pyre type checker 132 | .pyre/ 133 | 134 | # Archive files 135 | *.tar.gz 136 | -------------------------------------------------------------------------------- /plugins/lookup/scaleway_secret.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright: (c) 2025, Scaleway 3 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | 5 | DOCUMENTATION = r""" 6 | name: scaleway_secret 7 | author: 8 | - Guillaume Noale (@gnoale) 9 | short_description: Look up Scaleway secrets 10 | description: 11 | - Look up Scaleway secret version data 12 | options: 13 | _terms: 14 | description: The secret id or name for which to get the value(s). 15 | type: list 16 | elements: str 17 | required: true 18 | revision: 19 | description: The revision of the secret version to get the value(s). 20 | type: str 21 | default: latest 22 | attribute: 23 | description: The attribute of the secret version to get the value(s). 24 | choices: 25 | - data 26 | - description 27 | - revision 28 | - secret_id 29 | """ 30 | 31 | import uuid 32 | 33 | from ansible.plugins.lookup import LookupBase 34 | from ansible.errors import AnsibleError 35 | from ..module_utils.scaleway import build_scaleway_client 36 | from ..module_utils.scaleway_secret import get_secret_version, get_secret 37 | 38 | HAS_SCALEWAY = True 39 | try: 40 | from scaleway.secret.v1beta1.api import SecretV1Beta1API 41 | from scaleway import ScalewayException 42 | except ImportError: 43 | HAS_SCALEWAY = False 44 | 45 | 46 | def is_uuid(value: str) -> bool: 47 | try: 48 | uuid.UUID(value) 49 | return True 50 | except ValueError: 51 | return False 52 | 53 | 54 | class LookupModule(LookupBase): 55 | def run(self, terms, variables, **kwargs): 56 | if not HAS_SCALEWAY: 57 | raise AnsibleError("Scaleway SDK is not installed") 58 | 59 | self.set_options(var_options=variables, direct=kwargs) 60 | 61 | attribute = kwargs.get("attribute") 62 | 63 | client = build_scaleway_client() 64 | api = SecretV1Beta1API(client) 65 | 66 | results = [] 67 | 68 | for term in terms: 69 | arguments = {"revision": kwargs.get("revision", "latest")} 70 | 71 | if is_uuid(term): 72 | arguments["secret_id"] = term 73 | else: 74 | try: 75 | secret = get_secret(api, name=term) 76 | arguments["secret_id"] = secret.id 77 | except ScalewayException as scw_exception: 78 | raise AnsibleError(scw_exception) 79 | 80 | try: 81 | secret_version = get_secret_version(api, **arguments) 82 | except ScalewayException as scw_exception: 83 | raise AnsibleError(scw_exception) 84 | 85 | if attribute is not None: 86 | results.append(getattr(secret_version, attribute)) 87 | else: 88 | results.append(secret_version.data) 89 | 90 | return results 91 | -------------------------------------------------------------------------------- /galaxy.yml: -------------------------------------------------------------------------------- 1 | # See https://docs.ansible.com/ansible/latest/dev_guide/collections_galaxy_meta.html 2 | 3 | namespace: scaleway 4 | name: scaleway 5 | version: 2.7.0 6 | readme: README.md 7 | authors: 8 | - Ansible (https://github.com/ansible) 9 | - Scaleway (https://github.com/scaleway) 10 | - Nathanael Demacon (https://github.com/quantumsheep) 11 | description: Scaleway Ansible Collection. 12 | license_file: LICENSE 13 | tags: 14 | - scaleway 15 | - cloud 16 | - compute 17 | - instances 18 | repository: https://github.com/scaleway/ansible 19 | homepage: https://github.com/scaleway/ansible 20 | issues: https://github.com/scaleway/ansible/issues 21 | build_ignore: 22 | - .gitignore 23 | - changelogs/.plugin-cache.yaml 24 | - .DS_Store 25 | - "*.tar.gz" 26 | - "plugins/modules/scaleway_account_project.py" 27 | - "plugins/modules/scaleway_applesilicon_server.py" 28 | - "plugins/modules/scaleway_baremetal_server.py" 29 | - "plugins/modules/scaleway_container_cron.py" 30 | - "plugins/modules/scaleway_container_domain.py" 31 | - "plugins/modules/scaleway_container_namespace.py" 32 | - "plugins/modules/scaleway_container_token.py" 33 | - "plugins/modules/scaleway_container.py" 34 | - "plugins/modules/scaleway_domain_ssl_certificate.py" 35 | - "plugins/modules/scaleway_flexibleip_flexible_ip.py" 36 | - "plugins/modules/scaleway_function_cron.py" 37 | - "plugins/modules/scaleway_function_domain.py" 38 | - "plugins/modules/scaleway_function_namespace.py" 39 | - "plugins/modules/scaleway_function_token.py" 40 | - "plugins/modules/scaleway_function_trigger.py" 41 | - "plugins/modules/scaleway_function.py" 42 | - "plugins/modules/scaleway_iam_api_key.py" 43 | - "plugins/modules/scaleway_iam_application.py" 44 | - "plugins/modules/scaleway_iam_group.py" 45 | - "plugins/modules/scaleway_iam_policy.py" 46 | - "plugins/modules/scaleway_iam_ssh_key.py" 47 | - "plugins/modules/scaleway_instance_image.py" 48 | - "plugins/modules/scaleway_instance_ip.py" 49 | - "plugins/modules/scaleway_instance_placement_group.py" 50 | - "plugins/modules/scaleway_instance_private_nic.py" 51 | - "plugins/modules/scaleway_instance_security_group_rule.py" 52 | - "plugins/modules/scaleway_instance_security_group.py" 53 | - "plugins/modules/scaleway_instance_snapshot.py" 54 | - "plugins/modules/scaleway_instance_volume.py" 55 | - "plugins/modules/scaleway_iot_device.py" 56 | - "plugins/modules/scaleway_iot_hub.py" 57 | - "plugins/modules/scaleway_iot_network.py" 58 | - "plugins/modules/scaleway_iot_route.py" 59 | - "plugins/modules/scaleway_lb_acl.py" 60 | - "plugins/modules/scaleway_lb_backend.py" 61 | - "plugins/modules/scaleway_lb_certificate.py" 62 | - "plugins/modules/scaleway_lb_frontend.py" 63 | - "plugins/modules/scaleway_lb_route.py" 64 | - "plugins/modules/scaleway_lb_subscriber.py" 65 | - "plugins/modules/scaleway_lb.py" 66 | - "plugins/modules/scaleway_mnq_credential.py" 67 | - "plugins/modules/scaleway_mnq_namespace.py" 68 | - "plugins/modules/scaleway_rdb_database_backup.py" 69 | - "plugins/modules/scaleway_rdb_endpoint.py" 70 | - "plugins/modules/scaleway_rdb_instance.py" 71 | - "plugins/modules/scaleway_rdb_read_replica.py" 72 | - "plugins/modules/scaleway_rdb_snapshot.py" 73 | - "plugins/modules/scaleway_redis_cluster.py" 74 | - "plugins/modules/scaleway_registry_namespace.py" 75 | - "plugins/modules/scaleway_vpcgw_dhcp_entry.py" 76 | - "plugins/modules/scaleway_vpcgw_dhcp.py" 77 | - "plugins/modules/scaleway_vpcgw_gateway_network.py" 78 | - "plugins/modules/scaleway_vpcgw_gateway.py" 79 | - "plugins/modules/scaleway_vpcgw_ip.py" 80 | - "plugins/modules/scaleway_vpcgw_pat_rule.py" 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Scaleway Community Collection 2 | 3 | This collection contains modules and plugins for Ansible to automate the management of Scaleway infrastructure and services. 4 | 5 | ## Reach us 6 | 7 | You can contact us on our [Slack community](https://slack.scaleway.com/). 8 | 9 | ## Inventory 10 | 11 | * `scaleway.scaleway.scaleway`: dynamic inventory plugin for Scaleway's Instances, Elastic Metal and Apple Sillicon 12 | 13 | **Usage example:** 14 | 15 | **scw.yml** 16 | 17 | ```yaml 18 | plugin: scaleway.scaleway.scaleway 19 | profile: base-profile # your scaleway credentials profile 20 | hostnames: 21 | - hostname 22 | - id 23 | ``` 24 | 25 | `ansible-inventory -i scw.yml --list` will list all the hosts from the dynamic inventory. 26 | 27 | ## Lookup 28 | 29 | * `scaleway.scaleway.scaleway_secret`: lookup plugin for Scaleway's Secrets 30 | 31 | **Usage example:** 32 | 33 | ```yaml 34 | - hosts: localhost 35 | 36 | vars: 37 | secret_versions: "{{ lookup('scaleway.scaleway.scaleway_secret', 'secret-epic-lumiere', 'test') }}" 38 | 39 | tasks: 40 | - name: Debug secret versions 41 | ansible.builtin.debug: 42 | msg: "{{ secret_versions | split(',') | map('b64decode') }}" 43 | ``` 44 | 45 | will print the secret's secret data as a list: 46 | 47 | ```shell 48 | ok: [localhost] => { 49 | "msg": [ 50 | "test", 51 | "abcd" 52 | ] 53 | } 54 | ``` 55 | 56 | 57 | ## Authentication and Environment variables 58 | 59 | Authentication is handled with the `SCW_PROFILE` or the `SCW_ACCESS_KEY` and `SCW_SECRET_KEY` environment variables. 60 | 61 | Please check this [documentation](https://www.scaleway.com/en/docs/scaleway-sdk/reference-content/scaleway-configuration-file/) for detailed instructions on how to configure your Scaleway credentials. 62 | 63 | ## Installing the collection 64 | 65 | ### Locally 66 | 67 | You can clone this repository and install the collection locally with `ansible-galaxy collection install .` 68 | 69 | ### Galaxy 70 | 71 | ```sh 72 | ansible-galaxy collection install scaleway.scaleway 73 | ``` 74 | 75 | You can also include it in a requirements.yml file and install it via `ansible-galaxy collection install -r requirements.yml`, using the format: 76 | 77 | ```yaml 78 | --- 79 | collections: 80 | - name: scaleway.scaleway 81 | ``` 82 | Note that the python module dependencies are not installed by `ansible-galaxy`. 83 | They can be manually installed using pip: 84 | 85 | ```sh 86 | pip install -r requirements-scaleway.txt 87 | ``` 88 | 89 | Note that if you install the collection from Ansible Galaxy, it will not be upgraded automatically if you upgrade the Ansible package. To upgrade the collection to the latest available version, run the following command: 90 | 91 | ```sh 92 | ansible-galaxy collection install scaleway.scaleway --upgrade 93 | ``` 94 | 95 | You can also install a specific version of the collection, for example, if you need to downgrade when something is broken in the latest version (please report an issue in this repository). Use the following syntax: 96 | 97 | ```sh 98 | ansible-galaxy collection install scaleway.scaleway:==1.0.0 99 | ``` 100 | 101 | 102 | ## Useful links 103 | 104 | * [Scaleway](https://www.scaleway.com/) 105 | * [Scaleway Developers Website](https://developers.scaleway.com/) 106 | * [Ansible Documentation](https://docs.ansible.com/ansible/latest/index.html) 107 | * [Ansible Code of Conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html) 108 | 109 | ## Licensing 110 | 111 | GNU General Public License v3.0 or later. 112 | 113 | See [LICENSE](https://www.gnu.org/licenses/gpl-3.0.txt) to see the full text. 114 | -------------------------------------------------------------------------------- /plugins/module_utils/scaleway_secret.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, division, print_function 2 | 3 | from .model import Model, Secret, SecretVersion 4 | 5 | try: 6 | from scaleway.secret.v1beta1.api import SecretV1Beta1API 7 | from scaleway import ScalewayException 8 | except ImportError: 9 | HAS_SCALEWAY_SDK = False 10 | 11 | 12 | class SecretNotFound(Exception): 13 | pass 14 | 15 | 16 | def build_secret(parameters: dict) -> Secret: 17 | return Secret.build_model(parameters) 18 | 19 | 20 | def build_secret_version(parameters: dict) -> SecretVersion: 21 | return SecretVersion.build_model(parameters) 22 | 23 | 24 | def get_secret(api: "SecretV1Beta1API", **kwargs) -> Secret: 25 | """ 26 | Get a secret by secret_id or name 27 | """ 28 | if "secret_id" in kwargs: 29 | secret = api.get_secret(secret_id=kwargs["secret_id"]) 30 | 31 | elif "name" in kwargs: 32 | secrets = api.list_secrets(name=kwargs["name"], scheduled_for_deletion=False) 33 | 34 | if len(secrets.secrets) == 0: 35 | raise SecretNotFound(f"Secret {kwargs['name']} not found") 36 | 37 | secret = secrets.secrets[0] 38 | 39 | else: 40 | raise SecretNotFound("No secret_id or name provided") 41 | 42 | return build_secret(secret.__dict__) 43 | 44 | 45 | def get_secret_version(api: "SecretV1Beta1API", **kwargs) -> SecretVersion: 46 | """ 47 | Get a secret version by secret_id and revision 48 | """ 49 | revision = kwargs.get("revision", "latest") 50 | secret_version = api.get_secret_version( 51 | secret_id=kwargs["secret_id"], revision=revision 52 | ) 53 | 54 | secret_version_access = api.access_secret_version( 55 | secret_id=kwargs["secret_id"], 56 | revision=revision, 57 | ) 58 | 59 | return build_secret_version( 60 | {**secret_version.__dict__, "data": secret_version_access.data} 61 | ) 62 | 63 | 64 | def update_secret( 65 | api: "SecretV1Beta1API", parameters: dict, check_mode: bool = False 66 | ) -> tuple[bool, Secret, Secret]: 67 | """ 68 | Update a secret by checking the difference between the local and remote object 69 | 70 | The local object is builded from the parameters and act as the source of truth 71 | The remote object is retrieved from the API 72 | 73 | return changed, local_model, remote_model 74 | """ 75 | remote_model = get_secret(api, name=parameters.get("name")) 76 | 77 | # build and diff source model with the api one 78 | local_model = build_secret(parameters) 79 | local_model.id = remote_model.id 80 | 81 | diff = local_model.diff(remote_model) 82 | if len(diff) == 0: 83 | return False, local_model, remote_model 84 | 85 | if check_mode: 86 | return False, local_model, remote_model 87 | 88 | updated_secret = api.update_secret(secret_id=remote_model.id, **diff) 89 | 90 | return True, build_secret(updated_secret.__dict__), remote_model 91 | 92 | 93 | def is_duplicate(scw_exception: "ScalewayException") -> bool: 94 | """ 95 | Inspect the content of raw Scaleway API json response to determine if the error is due to a duplicate secret 96 | """ 97 | if scw_exception.status_code == 400: 98 | return ( 99 | scw_exception.response.json()["details"][0]["help_message"] 100 | == "cannot have same secret name in same path" 101 | ) 102 | return False 103 | 104 | 105 | def build_ansible_diff(remote_model: Model, local_model: Model) -> dict: 106 | """ 107 | Build an Ansible diff dictionary from a before and after model 108 | """ 109 | return dict( 110 | before=remote_model.__dict__, 111 | after=local_model.__dict__, 112 | ) 113 | -------------------------------------------------------------------------------- /CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | ================================ 2 | Community Scaleway Release Notes 3 | ================================ 4 | 5 | .. contents:: Topics 6 | 7 | 8 | v2.7.0 9 | ====== 10 | 11 | v2.5.0 12 | ====== 13 | 14 | v2.4.0 15 | ====== 16 | 17 | v2.3.0 18 | ====== 19 | 20 | v2.2.0 21 | ====== 22 | 23 | v2.1.0 24 | ====== 25 | 26 | New Modules 27 | ----------- 28 | 29 | - scaleway_account_project - Manage Scaleway account's project 30 | - scaleway_applesilicon_server - Manage Scaleway applesilicon's server 31 | - scaleway_baremetal_server - Manage Scaleway baremetal's server 32 | - scaleway_container - Manage Scaleway container's container 33 | - scaleway_container_cron - Manage Scaleway container's cron 34 | - scaleway_container_domain - Manage Scaleway container's domain 35 | - scaleway_container_namespace - Manage Scaleway container's namespace 36 | - scaleway_container_token - Manage Scaleway container's token 37 | - scaleway_domain_ssl_certificate - Manage Scaleway domain's ssl_certificate 38 | - scaleway_flexibleip_flexible_ip - Manage Scaleway flexibleip's flexible_ip 39 | - scaleway_function - Manage Scaleway function's function 40 | - scaleway_function_cron - Manage Scaleway function's cron 41 | - scaleway_function_domain - Manage Scaleway function's domain 42 | - scaleway_function_namespace - Manage Scaleway function's namespace 43 | - scaleway_function_token - Manage Scaleway function's token 44 | - scaleway_function_trigger - Manage Scaleway function's trigger 45 | - scaleway_iam_api_key - Manage Scaleway iam's api_key 46 | - scaleway_iam_application - Manage Scaleway iam's application 47 | - scaleway_iam_group - Manage Scaleway iam's group 48 | - scaleway_iam_policy - Manage Scaleway iam's policy 49 | - scaleway_iam_ssh_key - Manage Scaleway iam's ssh_key 50 | - scaleway_instance_image - Manage Scaleway instance's image 51 | - scaleway_instance_ip - Manage Scaleway instance's ip 52 | - scaleway_instance_placement_group - Manage Scaleway instance's placement_group 53 | - scaleway_instance_private_nic - Manage Scaleway instance's private_nic 54 | - scaleway_instance_security_group - Manage Scaleway instance's security_group 55 | - scaleway_instance_security_group_rule - Manage Scaleway instance's security_group_rule 56 | - scaleway_instance_snapshot - Manage Scaleway instance's snapshot 57 | - scaleway_instance_volume - Manage Scaleway instance's volume 58 | - scaleway_iot_device - Manage Scaleway iot's device 59 | - scaleway_iot_hub - Manage Scaleway iot's hub 60 | - scaleway_iot_network - Manage Scaleway iot's network 61 | - scaleway_iot_route - Manage Scaleway iot's route 62 | - scaleway_k8s_cluster - Manage Scaleway k8s's cluster 63 | - scaleway_k8s_pool - Manage Scaleway k8s's pool 64 | - scaleway_lb - Manage Scaleway lb's lb 65 | - scaleway_lb_acl - Manage Scaleway lb's acl 66 | - scaleway_lb_backend - Manage Scaleway lb's backend 67 | - scaleway_lb_certificate - Manage Scaleway lb's certificate 68 | - scaleway_lb_frontend - Manage Scaleway lb's frontend 69 | - scaleway_lb_route - Manage Scaleway lb's route 70 | - scaleway_lb_subscriber - Manage Scaleway lb's subscriber 71 | - scaleway_mnq_credential - Manage Scaleway mnq's credential 72 | - scaleway_mnq_namespace - Manage Scaleway mnq's namespace 73 | - scaleway_rdb_database_backup - Manage Scaleway rdb's database_backup 74 | - scaleway_rdb_endpoint - Manage Scaleway rdb's endpoint 75 | - scaleway_rdb_instance - Manage Scaleway rdb's instance 76 | - scaleway_rdb_read_replica - Manage Scaleway rdb's read_replica 77 | - scaleway_rdb_snapshot - Manage Scaleway rdb's snapshot 78 | - scaleway_redis_cluster - Manage Scaleway redis's cluster 79 | - scaleway_registry_namespace - Manage Scaleway registry's namespace 80 | - scaleway_secret - Manage Scaleway secret's secret 81 | - scaleway_vpc_private_network - Manage Scaleway vpc's private_network 82 | - scaleway_vpcgw_dhcp - Manage Scaleway vpcgw's dhcp 83 | - scaleway_vpcgw_dhcp_entry - Manage Scaleway vpcgw's dhcp_entry 84 | - scaleway_vpcgw_gateway - Manage Scaleway vpcgw's gateway 85 | - scaleway_vpcgw_gateway_network - Manage Scaleway vpcgw's gateway_network 86 | - scaleway_vpcgw_ip - Manage Scaleway vpcgw's ip 87 | - scaleway_vpcgw_pat_rule - Manage Scaleway vpcgw's pat_rule 88 | 89 | v2.0.0 90 | ====== 91 | 92 | v1.2.0 93 | ====== 94 | 95 | v1.1.0 96 | ====== 97 | 98 | Minor Changes 99 | ------------- 100 | 101 | - scaleway inventory script - add elastic metal and apple silicon support 102 | 103 | v1.0.0 104 | ====== 105 | 106 | New Plugins 107 | ----------- 108 | 109 | Inventory 110 | ~~~~~~~~~ 111 | 112 | - scaleway - Scaleway inventory source 113 | -------------------------------------------------------------------------------- /tests/integration/targets/scaleway_secret/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create a new secret 3 | scaleway.scaleway.scaleway_secret: 4 | name: "ansible-test-secret" 5 | register: secret 6 | 7 | - name: Re create the secret - no update 8 | scaleway.scaleway.scaleway_secret: 9 | name: "ansible-test-secret" 10 | register: secret 11 | 12 | - name: Assert no update 13 | ansible.builtin.assert: 14 | that: 15 | - secret.changed == False 16 | - secret.diff.before == secret.diff.after 17 | 18 | - name: Update secret 19 | scaleway.scaleway.scaleway_secret: 20 | name: "ansible-test-secret" 21 | description: "updated description" 22 | register: secret 23 | 24 | - name: Assert secret updated 25 | ansible.builtin.assert: 26 | that: 27 | - secret.changed == True 28 | - secret.data.description == "updated description" 29 | - secret.diff.before.description == "" 30 | - secret.diff.after.description == "updated description" 31 | 32 | - name: Update secret in check mode 33 | scaleway.scaleway.scaleway_secret: 34 | name: "ansible-test-secret" 35 | description: "updated description" 36 | tags: 37 | - "tag1" 38 | - "tag2" 39 | register: secret 40 | check_mode: true 41 | 42 | - name: Assert secret is not updated 43 | ansible.builtin.assert: 44 | that: 45 | - secret.changed == False 46 | - secret.diff.before.tags == [] 47 | - secret.diff.after.tags == ["tag1", "tag2"] 48 | 49 | - name: Create a secret version 50 | scaleway.scaleway.scaleway_secret_version: 51 | secret_id: "{{ secret.data.id }}" 52 | data: "confidential data" 53 | register: secret_version 54 | 55 | - name: Assert secret version created 56 | ansible.builtin.assert: 57 | that: 58 | - secret_version.changed == True 59 | - secret_version.data.revision == 1 60 | 61 | - name: Lookup secret by name 62 | ansible.builtin.set_fact: 63 | secret_value: "{{ lookup('scaleway.scaleway.scaleway_secret', 'ansible-test-secret') }}" 64 | 65 | - name: Assert Secret Version lookup data 66 | ansible.builtin.assert: 67 | that: 68 | - secret_value | b64decode == 'confidential data' 69 | 70 | - name: Lookup secret revision by id 71 | ansible.builtin.set_fact: 72 | secret_revision: "{{ lookup('scaleway.scaleway.scaleway_secret', '{{ secret.data.id }}', attribute='revision') }}" 73 | 74 | - name: Assert secret revision lookup data 75 | ansible.builtin.assert: 76 | that: 77 | - secret_revision | string == "1" # ansible < 2.17 return a string 78 | 79 | - name: Create a secret version in check mode 80 | scaleway.scaleway.scaleway_secret_version: 81 | secret_id: "{{ secret.data.id }}" 82 | data: "confidential data" 83 | check_mode: true 84 | register: secret_version_check 85 | 86 | - name: Assert secret version is not updated 87 | ansible.builtin.assert: 88 | that: 89 | - secret_version_check.changed == False 90 | 91 | - name: Force create a new secret version (same data) 92 | scaleway.scaleway.scaleway_secret_version: 93 | secret_id: "{{ secret.data.id }}" 94 | data: "confidential data" 95 | force_new_version: true 96 | register: secret_version 97 | 98 | - name: Assert secret version incremented 99 | ansible.builtin.assert: 100 | that: 101 | - secret_version.changed == True 102 | - secret_version.data.revision == 2 103 | 104 | - name: Create a new secret version with different data 105 | scaleway.scaleway.scaleway_secret_version: 106 | secret_id: "{{ secret.data.id }}" 107 | data: "different data" 108 | register: secret_version 109 | 110 | - name: Assert secret version incremented 111 | ansible.builtin.assert: 112 | that: 113 | - secret_version.changed == True 114 | - secret_version.data.revision == 3 115 | 116 | - name: Create a new secret version with the same data (no force) 117 | scaleway.scaleway.scaleway_secret_version: 118 | secret_id: "{{ secret.data.id }}" 119 | data: "different data" 120 | register: secret_version_noop 121 | 122 | - name: Assert secret version is not updated 123 | ansible.builtin.assert: 124 | that: 125 | - secret_version_noop.changed == False 126 | 127 | - name: Delete secret version 128 | scaleway.scaleway.scaleway_secret_version: 129 | secret_id: "{{ secret.data.id }}" 130 | revision: "{{ secret_version.data.revision }}" 131 | state: absent 132 | 133 | - name: Delete secret 134 | scaleway.scaleway.scaleway_secret: 135 | name: "ansible-test-secret" 136 | state: absent 137 | 138 | - name: Create secret in check mode 139 | scaleway.scaleway.scaleway_secret: 140 | name: "ansible-test-secret" 141 | description: "updated description" 142 | tags: 143 | - "tag1" 144 | - "tag2" 145 | register: secret 146 | check_mode: true 147 | -------------------------------------------------------------------------------- /tests/unit/plugins/conftest.py: -------------------------------------------------------------------------------- 1 | import tempfile 2 | import os 3 | import yaml 4 | import pytest 5 | import uuid 6 | import json 7 | from ansible.module_utils import basic 8 | from ansible.module_utils.common.text.converters import to_bytes 9 | from scaleway_core.profile import Profile 10 | 11 | from scaleway.baremetal.v1.types import Server, IP, IPVersion, IPReverseStatus 12 | 13 | 14 | @pytest.fixture() 15 | def set_module_args(request): 16 | """prepare arguments so that they will be picked up during module creation""" 17 | args = json.dumps({"ANSIBLE_MODULE_ARGS": request.param}) 18 | basic._ANSIBLE_ARGS = to_bytes(args) 19 | # ansible-core 2.19 require this to be set when tests run in the CI 20 | # this is the file I assume it needs to resolve as decoders 21 | # .venv/lib/python3.13/site-packages/ansible/module_utils/_internal/_json/_profiles/__pycache__/_module_modern_c2m.cpython-313.pyc 22 | # I couldn't reproduce the issue locally though 23 | try: 24 | basic._ANSIBLE_PROFILE = "modern" 25 | except AttributeError: 26 | pass 27 | 28 | 29 | @pytest.fixture(name="scaleway_config_profile") 30 | def create_temporary_scaleway_config() -> Profile: 31 | # Create a temporary config file with the default project id that will be attached to the client 32 | with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp: 33 | config_file = tmp.name 34 | sample_uuid = str(uuid.uuid4()) 35 | yaml.dump( 36 | { 37 | "access_key": "SCWXXXXXXXXXXXXXXXXX", 38 | "secret_key": sample_uuid, 39 | "default_project_id": sample_uuid, 40 | "default_region": "fr-par", 41 | "default_organization_id": sample_uuid, 42 | }, 43 | tmp, 44 | ) 45 | 46 | os.environ["SCW_CONFIG_PATH"] = config_file 47 | return Profile.from_config_file(config_file) 48 | 49 | 50 | @pytest.fixture(name="list_bare_metals") 51 | def list_bare_metals_fixture(): 52 | return [ 53 | Server( 54 | id="bmc-12345678-1234-1234-1234-123456789012", 55 | organization_id="org-12345678-1234-1234-1234-123456789012", 56 | project_id="project-12345678-1234-1234-1234-123456789012", 57 | name="test-bare-metal", 58 | description="A test bare metal server", 59 | status="running", 60 | updated_at="2023-10-01T12:00:00Z", 61 | created_at="2023-10-01T10:00:00Z", 62 | offer_id="bmc-2xlarge", 63 | offer_name="bmc-2xlarge", 64 | tags=["prod", "platform2"], 65 | boot_type="local", 66 | zone="fr-par-1", 67 | ping_status="ping_running", 68 | domain="test.example.com", 69 | options=[], 70 | install=None, 71 | rescue_server=None, 72 | ips=[ 73 | IP( 74 | address="1.1.1.1", 75 | reverse="test.example.com", 76 | id="ip-12345678-1234-1234-1234-123456789012", 77 | version=IPVersion.I_PV4, 78 | reverse_status=IPReverseStatus.ACTIVE, 79 | reverse_status_message="", 80 | ), 81 | IP( 82 | address="192.168.0.1", 83 | version=IPVersion.I_PV4, 84 | reverse="test.internal", 85 | id="ip-12345678-1234-1234-1234-123456789012", 86 | reverse_status=IPReverseStatus.ACTIVE, 87 | reverse_status_message="", 88 | ), 89 | ], 90 | ), 91 | Server( 92 | id="bmc-12345678-1234-1234-1234-123456789012", 93 | organization_id="org-12345678-1234-1234-1234-123456789012", 94 | project_id="project-12345678-1234-1234-1234-123456789012", 95 | name="test-bare-metal", 96 | description="A test bare metal server", 97 | status="stopped", 98 | updated_at="2023-10-01T12:00:00Z", 99 | created_at="2023-10-01T10:00:00Z", 100 | offer_id="bmc-2xlarge", 101 | offer_name="bmc-2xlarge", 102 | tags=["dev", "platform1"], 103 | boot_type="local", 104 | zone="fr-par-1", 105 | ping_status="ping_running", 106 | domain="test.example.com", 107 | options=[], 108 | install=None, 109 | rescue_server=None, 110 | ips=[ 111 | IP( 112 | address="1.1.1.1", 113 | reverse="test.example.com", 114 | id="ip-12345678-1234-1234-1234-123456789012", 115 | version=IPVersion.I_PV4, 116 | reverse_status=IPReverseStatus.ACTIVE, 117 | reverse_status_message="", 118 | ), 119 | IP( 120 | address="2001:db8::1", 121 | version=IPVersion.I_PV6, 122 | reverse="test.internal", 123 | id="ip-12345678-1234-1234-1234-123456789012", 124 | reverse_status=IPReverseStatus.ACTIVE, 125 | reverse_status_message="", 126 | ), 127 | ], 128 | ), 129 | ] 130 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_vpcgw_ip.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_vpcgw_ip 13 | short_description: Manage Scaleway vpcgw's ip 14 | description: 15 | - This module can be used to manage Scaleway vpcgw's ip. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | ip_id: 34 | description: ip_id 35 | type: str 36 | required: false 37 | zone: 38 | description: zone 39 | type: str 40 | required: false 41 | project_id: 42 | description: project_id 43 | type: str 44 | required: false 45 | tags: 46 | description: tags 47 | type: list 48 | elements: str 49 | required: false 50 | """ 51 | 52 | EXAMPLES = r""" 53 | - name: Create a ip 54 | scaleway.scaleway.scaleway_vpcgw_ip: 55 | access_key: "{{ scw_access_key }}" 56 | secret_key: "{{ scw_secret_key }}" 57 | """ 58 | 59 | RETURN = r""" 60 | --- 61 | ip: 62 | description: The ip information 63 | returned: when I(state=present) 64 | type: dict 65 | sample: 66 | id: 00000000-0000-0000-0000-000000000000 67 | organization_id: 00000000-0000-0000-0000-000000000000 68 | project_id: 00000000-0000-0000-0000-000000000000 69 | created_at: "aaaaaa" 70 | updated_at: "aaaaaa" 71 | tags: 72 | - aaaaaa 73 | - bbbbbb 74 | address: "aaaaaa" 75 | reverse: "aaaaaa" 76 | gateway_id: 00000000-0000-0000-0000-000000000000 77 | zone: "aaaaaa" 78 | """ 79 | 80 | from ansible.module_utils.basic import ( 81 | AnsibleModule, 82 | missing_required_lib, 83 | ) 84 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 85 | scaleway_argument_spec, 86 | scaleway_waitable_resource_argument_spec, 87 | scaleway_get_client_from_module, 88 | scaleway_pop_client_params, 89 | scaleway_pop_waitable_resource_params, 90 | ) 91 | 92 | try: 93 | from scaleway import Client 94 | from scaleway.vpcgw.v1 import VpcgwV1API 95 | 96 | HAS_SCALEWAY_SDK = True 97 | except ImportError: 98 | HAS_SCALEWAY_SDK = False 99 | 100 | 101 | def create(module: AnsibleModule, client: "Client") -> None: 102 | api = VpcgwV1API(client) 103 | 104 | id = module.params.pop("id", None) 105 | if id is not None: 106 | resource = api.get_ip(ip_id=id) 107 | 108 | if module.check_mode: 109 | module.exit_json(changed=False) 110 | 111 | module.exit_json(changed=False, data=resource) 112 | 113 | if module.check_mode: 114 | module.exit_json(changed=True) 115 | 116 | not_none_params = { 117 | key: value for key, value in module.params.items() if value is not None 118 | } 119 | resource = api.create_ip(**not_none_params) 120 | 121 | module.exit_json(changed=True, data=resource.__dict__) 122 | 123 | 124 | def delete(module: AnsibleModule, client: "Client") -> None: 125 | api = VpcgwV1API(client) 126 | 127 | id = module.params.pop("id", None) 128 | 129 | if id is not None: 130 | resource = api.get_ip(ip_id=id, region=module.params["region"]) 131 | else: 132 | module.fail_json(msg="id is required") 133 | 134 | if module.check_mode: 135 | module.exit_json(changed=True) 136 | 137 | api.delete_ip(ip_id=resource.id, region=module.params["region"]) 138 | 139 | module.exit_json( 140 | changed=True, 141 | msg=f"vpcgw's ip {resource.id} deleted", 142 | ) 143 | 144 | 145 | def core(module: AnsibleModule) -> None: 146 | client = scaleway_get_client_from_module(module) 147 | 148 | state = module.params.pop("state") 149 | scaleway_pop_client_params(module) 150 | scaleway_pop_waitable_resource_params(module) 151 | 152 | if state == "present": 153 | create(module, client) 154 | elif state == "absent": 155 | delete(module, client) 156 | 157 | 158 | def main() -> None: 159 | argument_spec = scaleway_argument_spec() 160 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 161 | argument_spec.update( 162 | state=dict(type="str", default="present", choices=["absent", "present"]), 163 | ip_id=dict(type="str"), 164 | zone=dict( 165 | type="str", 166 | required=False, 167 | ), 168 | project_id=dict( 169 | type="str", 170 | required=False, 171 | ), 172 | tags=dict( 173 | type="list", 174 | required=False, 175 | elements="str", 176 | ), 177 | ) 178 | 179 | module = AnsibleModule( 180 | argument_spec=argument_spec, 181 | supports_check_mode=True, 182 | ) 183 | 184 | if not HAS_SCALEWAY_SDK: 185 | module.fail_json(msg=missing_required_lib("scaleway")) 186 | 187 | core(module) 188 | 189 | 190 | if __name__ == "__main__": 191 | main() 192 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_instance_ip.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_instance_ip 13 | short_description: Manage Scaleway instance's ip 14 | description: 15 | - This module can be used to manage Scaleway instance's ip. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | ip: 34 | description: ip 35 | type: str 36 | required: false 37 | zone: 38 | description: zone 39 | type: str 40 | required: false 41 | organization: 42 | description: organization 43 | type: str 44 | required: false 45 | project: 46 | description: project 47 | type: str 48 | required: false 49 | tags: 50 | description: tags 51 | type: list 52 | elements: str 53 | required: false 54 | server: 55 | description: server 56 | type: str 57 | required: false 58 | """ 59 | 60 | EXAMPLES = r""" 61 | - name: Create a ip 62 | scaleway.scaleway.scaleway_instance_ip: 63 | access_key: "{{ scw_access_key }}" 64 | secret_key: "{{ scw_secret_key }}" 65 | """ 66 | 67 | RETURN = r""" 68 | --- 69 | ip: 70 | description: The ip information 71 | returned: when I(state=present) 72 | type: dict 73 | sample: 74 | ip: 75 | aaaaaa: bbbbbb 76 | cccccc: dddddd 77 | """ 78 | 79 | from ansible.module_utils.basic import ( 80 | AnsibleModule, 81 | missing_required_lib, 82 | ) 83 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 84 | scaleway_argument_spec, 85 | scaleway_waitable_resource_argument_spec, 86 | scaleway_get_client_from_module, 87 | scaleway_pop_client_params, 88 | scaleway_pop_waitable_resource_params, 89 | ) 90 | 91 | try: 92 | from scaleway import Client 93 | from scaleway.instance.v1 import InstanceV1API 94 | 95 | HAS_SCALEWAY_SDK = True 96 | except ImportError: 97 | HAS_SCALEWAY_SDK = False 98 | 99 | 100 | def create(module: AnsibleModule, client: "Client") -> None: 101 | api = InstanceV1API(client) 102 | 103 | id = module.params.pop("id", None) 104 | if id is not None: 105 | resource = api.get_ip(ip=id) 106 | 107 | if module.check_mode: 108 | module.exit_json(changed=False) 109 | 110 | module.exit_json(changed=False, data=resource) 111 | 112 | if module.check_mode: 113 | module.exit_json(changed=True) 114 | 115 | not_none_params = { 116 | key: value for key, value in module.params.items() if value is not None 117 | } 118 | resource = api.create_ip(**not_none_params) 119 | 120 | module.exit_json(changed=True, data=resource.__dict__) 121 | 122 | 123 | def delete(module: AnsibleModule, client: "Client") -> None: 124 | api = InstanceV1API(client) 125 | 126 | ip = module.params.pop("ip", None) 127 | 128 | if ip is not None: 129 | resource = api.get_ip(ip=ip, region=module.params["region"]) 130 | else: 131 | module.fail_json(msg="ip is required") 132 | 133 | if module.check_mode: 134 | module.exit_json(changed=True) 135 | 136 | api.delete_ip(ip=resource.ip, region=module.params["region"]) 137 | 138 | module.exit_json( 139 | changed=True, 140 | msg=f"instance's ip {resource.ip} deleted", 141 | ) 142 | 143 | 144 | def core(module: AnsibleModule) -> None: 145 | client = scaleway_get_client_from_module(module) 146 | 147 | state = module.params.pop("state") 148 | scaleway_pop_client_params(module) 149 | scaleway_pop_waitable_resource_params(module) 150 | 151 | if state == "present": 152 | create(module, client) 153 | elif state == "absent": 154 | delete(module, client) 155 | 156 | 157 | def main() -> None: 158 | argument_spec = scaleway_argument_spec() 159 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 160 | argument_spec.update( 161 | state=dict(type="str", default="present", choices=["absent", "present"]), 162 | ip=dict(type="str"), 163 | zone=dict( 164 | type="str", 165 | required=False, 166 | ), 167 | organization=dict( 168 | type="str", 169 | required=False, 170 | ), 171 | project=dict( 172 | type="str", 173 | required=False, 174 | ), 175 | tags=dict( 176 | type="list", 177 | required=False, 178 | elements="str", 179 | ), 180 | server=dict( 181 | type="str", 182 | required=False, 183 | ), 184 | ) 185 | 186 | module = AnsibleModule( 187 | argument_spec=argument_spec, 188 | supports_check_mode=True, 189 | ) 190 | 191 | if not HAS_SCALEWAY_SDK: 192 | module.fail_json(msg=missing_required_lib("scaleway")) 193 | 194 | core(module) 195 | 196 | 197 | if __name__ == "__main__": 198 | main() 199 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_instance_private_nic.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_instance_private_nic 13 | short_description: Manage Scaleway instance's private_nic 14 | description: 15 | - This module can be used to manage Scaleway instance's private_nic. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | server_id: 34 | description: server_id 35 | type: str 36 | required: true 37 | private_network_id: 38 | description: private_network_id 39 | type: str 40 | required: true 41 | zone: 42 | description: zone 43 | type: str 44 | required: false 45 | tags: 46 | description: tags 47 | type: list 48 | elements: str 49 | required: false 50 | """ 51 | 52 | EXAMPLES = r""" 53 | - name: Create a private_nic 54 | scaleway.scaleway.scaleway_instance_private_nic: 55 | access_key: "{{ scw_access_key }}" 56 | secret_key: "{{ scw_secret_key }}" 57 | server_id: "aaaaaa" 58 | private_network_id: "aaaaaa" 59 | """ 60 | 61 | RETURN = r""" 62 | --- 63 | private_nic: 64 | description: The private_nic information 65 | returned: when I(state=present) 66 | type: dict 67 | sample: 68 | private_nic: 69 | aaaaaa: bbbbbb 70 | cccccc: dddddd 71 | """ 72 | 73 | from ansible.module_utils.basic import ( 74 | AnsibleModule, 75 | missing_required_lib, 76 | ) 77 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 78 | scaleway_argument_spec, 79 | scaleway_waitable_resource_argument_spec, 80 | scaleway_get_client_from_module, 81 | scaleway_pop_client_params, 82 | scaleway_pop_waitable_resource_params, 83 | ) 84 | 85 | try: 86 | from scaleway import Client 87 | from scaleway.instance.v1 import InstanceV1API 88 | 89 | HAS_SCALEWAY_SDK = True 90 | except ImportError: 91 | HAS_SCALEWAY_SDK = False 92 | 93 | 94 | def create(module: AnsibleModule, client: "Client") -> None: 95 | api = InstanceV1API(client) 96 | 97 | id = module.params.pop("id", None) 98 | if id is not None: 99 | resource = api.get_private_nic(server_id=id) 100 | 101 | if module.check_mode: 102 | module.exit_json(changed=False) 103 | 104 | module.exit_json(changed=False, data=resource) 105 | 106 | if module.check_mode: 107 | module.exit_json(changed=True) 108 | 109 | not_none_params = { 110 | key: value for key, value in module.params.items() if value is not None 111 | } 112 | resource = api.create_private_nic(**not_none_params) 113 | 114 | module.exit_json(changed=True, data=resource.__dict__) 115 | 116 | 117 | def delete(module: AnsibleModule, client: "Client") -> None: 118 | api = InstanceV1API(client) 119 | 120 | private_nic = module.params.pop("private_nic", None) 121 | 122 | if private_nic is not None: 123 | resource = api.get_private_nic( 124 | server_id=private_nic, region=module.params["region"] 125 | ) 126 | else: 127 | module.fail_json(msg="private_nic is required") 128 | 129 | if module.check_mode: 130 | module.exit_json(changed=True) 131 | 132 | api.delete_private_nic( 133 | server_id=resource.private_nic, region=module.params["region"] 134 | ) 135 | 136 | module.exit_json( 137 | changed=True, 138 | msg=f"instance's private_nic {resource.private_nic} deleted", 139 | ) 140 | 141 | 142 | def core(module: AnsibleModule) -> None: 143 | client = scaleway_get_client_from_module(module) 144 | 145 | state = module.params.pop("state") 146 | scaleway_pop_client_params(module) 147 | scaleway_pop_waitable_resource_params(module) 148 | 149 | if state == "present": 150 | create(module, client) 151 | elif state == "absent": 152 | delete(module, client) 153 | 154 | 155 | def main() -> None: 156 | argument_spec = scaleway_argument_spec() 157 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 158 | argument_spec.update( 159 | state=dict(type="str", default="present", choices=["absent", "present"]), 160 | server_id=dict( 161 | type="str", 162 | required=True, 163 | ), 164 | private_network_id=dict( 165 | type="str", 166 | required=True, 167 | ), 168 | zone=dict( 169 | type="str", 170 | required=False, 171 | ), 172 | tags=dict( 173 | type="list", 174 | required=False, 175 | elements="str", 176 | ), 177 | ) 178 | 179 | module = AnsibleModule( 180 | argument_spec=argument_spec, 181 | supports_check_mode=True, 182 | ) 183 | 184 | if not HAS_SCALEWAY_SDK: 185 | module.fail_json(msg=missing_required_lib("scaleway")) 186 | 187 | core(module) 188 | 189 | 190 | if __name__ == "__main__": 191 | main() 192 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_domain_ssl_certificate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_domain_ssl_certificate 13 | short_description: Manage Scaleway domain's ssl_certificate 14 | description: 15 | - This module can be used to manage Scaleway domain's ssl_certificate. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | dns_zone: 34 | description: dns_zone 35 | type: str 36 | required: true 37 | alternative_dns_zones: 38 | description: alternative_dns_zones 39 | type: list 40 | elements: str 41 | required: false 42 | """ 43 | 44 | EXAMPLES = r""" 45 | - name: Create a ssl_certificate 46 | scaleway.scaleway.scaleway_domain_ssl_certificate: 47 | access_key: "{{ scw_access_key }}" 48 | secret_key: "{{ scw_secret_key }}" 49 | dns_zone: "aaaaaa" 50 | """ 51 | 52 | RETURN = r""" 53 | --- 54 | ssl_certificate: 55 | description: The ssl_certificate information 56 | returned: when I(state=present) 57 | type: dict 58 | sample: 59 | dns_zone: "aaaaaa" 60 | alternative_dns_zones: 61 | - aaaaaa 62 | - bbbbbb 63 | status: new 64 | private_key: "aaaaaa" 65 | certificate_chain: "aaaaaa" 66 | created_at: "aaaaaa" 67 | expired_at: "aaaaaa" 68 | """ 69 | 70 | from ansible.module_utils.basic import ( 71 | AnsibleModule, 72 | missing_required_lib, 73 | ) 74 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 75 | scaleway_argument_spec, 76 | scaleway_waitable_resource_argument_spec, 77 | scaleway_get_client_from_module, 78 | scaleway_pop_client_params, 79 | scaleway_pop_waitable_resource_params, 80 | ) 81 | 82 | try: 83 | from scaleway import Client, ScalewayException 84 | from scaleway.domain.v2beta1 import DomainV2Beta1API 85 | 86 | HAS_SCALEWAY_SDK = True 87 | except ImportError: 88 | HAS_SCALEWAY_SDK = False 89 | 90 | 91 | def create(module: AnsibleModule, client: "Client") -> None: 92 | api = DomainV2Beta1API(client) 93 | 94 | id = module.params.pop("id", None) 95 | if id is not None: 96 | resource = api.get_ssl_certificate(dns_zone=id) 97 | 98 | if module.check_mode: 99 | module.exit_json(changed=False) 100 | 101 | module.exit_json(changed=False, data=resource) 102 | 103 | if module.check_mode: 104 | module.exit_json(changed=True) 105 | 106 | not_none_params = { 107 | key: value for key, value in module.params.items() if value is not None 108 | } 109 | resource = api.create_ssl_certificate(**not_none_params) 110 | resource = api.wait_for_ssl_certificate( 111 | dns_zone=resource.dns_zone, region=module.params["region"] 112 | ) 113 | 114 | module.exit_json(changed=True, data=resource.__dict__) 115 | 116 | 117 | def delete(module: AnsibleModule, client: "Client") -> None: 118 | api = DomainV2Beta1API(client) 119 | 120 | dns_zone = module.params.pop("dns_zone", None) 121 | 122 | if dns_zone is not None: 123 | resource = api.get_ssl_certificate( 124 | dns_zone=dns_zone, region=module.params["region"] 125 | ) 126 | else: 127 | module.fail_json(msg="dns_zone is required") 128 | 129 | if module.check_mode: 130 | module.exit_json(changed=True) 131 | 132 | api.delete_ssl_certificate( 133 | dns_zone=resource.dns_zone, region=module.params["region"] 134 | ) 135 | 136 | try: 137 | api.wait_for_ssl_certificate( 138 | dns_zone=resource.dns_zone, region=module.params["region"] 139 | ) 140 | except ScalewayException as e: 141 | if e.status_code != 404: 142 | raise e 143 | 144 | module.exit_json( 145 | changed=True, 146 | msg=f"domain's ssl_certificate {resource.dns_zone} deleted", 147 | ) 148 | 149 | 150 | def core(module: AnsibleModule) -> None: 151 | client = scaleway_get_client_from_module(module) 152 | 153 | state = module.params.pop("state") 154 | scaleway_pop_client_params(module) 155 | scaleway_pop_waitable_resource_params(module) 156 | 157 | if state == "present": 158 | create(module, client) 159 | elif state == "absent": 160 | delete(module, client) 161 | 162 | 163 | def main() -> None: 164 | argument_spec = scaleway_argument_spec() 165 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 166 | argument_spec.update( 167 | state=dict(type="str", default="present", choices=["absent", "present"]), 168 | dns_zone=dict( 169 | type="str", 170 | required=True, 171 | ), 172 | alternative_dns_zones=dict( 173 | type="list", 174 | required=False, 175 | elements="str", 176 | ), 177 | ) 178 | 179 | module = AnsibleModule( 180 | argument_spec=argument_spec, 181 | supports_check_mode=True, 182 | ) 183 | 184 | if not HAS_SCALEWAY_SDK: 185 | module.fail_json(msg=missing_required_lib("scaleway")) 186 | 187 | core(module) 188 | 189 | 190 | if __name__ == "__main__": 191 | main() 192 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_lb_route.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_lb_route 13 | short_description: Manage Scaleway lb's route 14 | description: 15 | - This module can be used to manage Scaleway lb's route. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | route_id: 34 | description: route_id 35 | type: str 36 | required: false 37 | frontend_id: 38 | description: frontend_id 39 | type: str 40 | required: true 41 | backend_id: 42 | description: backend_id 43 | type: str 44 | required: true 45 | region: 46 | description: region 47 | type: str 48 | required: false 49 | choices: 50 | - fr-par 51 | - nl-ams 52 | - pl-waw 53 | match: 54 | description: match 55 | type: dict 56 | required: false 57 | """ 58 | 59 | EXAMPLES = r""" 60 | - name: Create a route 61 | scaleway.scaleway.scaleway_lb_route: 62 | access_key: "{{ scw_access_key }}" 63 | secret_key: "{{ scw_secret_key }}" 64 | frontend_id: "aaaaaa" 65 | backend_id: "aaaaaa" 66 | """ 67 | 68 | RETURN = r""" 69 | --- 70 | route: 71 | description: The route information 72 | returned: when I(state=present) 73 | type: dict 74 | sample: 75 | id: 00000000-0000-0000-0000-000000000000 76 | frontend_id: 00000000-0000-0000-0000-000000000000 77 | backend_id: 00000000-0000-0000-0000-000000000000 78 | match: 79 | aaaaaa: bbbbbb 80 | cccccc: dddddd 81 | created_at: "aaaaaa" 82 | updated_at: "aaaaaa" 83 | """ 84 | 85 | from ansible.module_utils.basic import ( 86 | AnsibleModule, 87 | missing_required_lib, 88 | ) 89 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 90 | scaleway_argument_spec, 91 | scaleway_waitable_resource_argument_spec, 92 | scaleway_get_client_from_module, 93 | scaleway_pop_client_params, 94 | scaleway_pop_waitable_resource_params, 95 | ) 96 | 97 | try: 98 | from scaleway import Client 99 | from scaleway.lb.v1 import LbV1API 100 | 101 | HAS_SCALEWAY_SDK = True 102 | except ImportError: 103 | HAS_SCALEWAY_SDK = False 104 | 105 | 106 | def create(module: AnsibleModule, client: "Client") -> None: 107 | api = LbV1API(client) 108 | 109 | id = module.params.pop("id", None) 110 | if id is not None: 111 | resource = api.get_route(route_id=id) 112 | 113 | if module.check_mode: 114 | module.exit_json(changed=False) 115 | 116 | module.exit_json(changed=False, data=resource) 117 | 118 | if module.check_mode: 119 | module.exit_json(changed=True) 120 | 121 | not_none_params = { 122 | key: value for key, value in module.params.items() if value is not None 123 | } 124 | resource = api.create_route(**not_none_params) 125 | 126 | module.exit_json(changed=True, data=resource.__dict__) 127 | 128 | 129 | def delete(module: AnsibleModule, client: "Client") -> None: 130 | api = LbV1API(client) 131 | 132 | id = module.params.pop("id", None) 133 | 134 | if id is not None: 135 | resource = api.get_route(route_id=id, region=module.params["region"]) 136 | else: 137 | module.fail_json(msg="id is required") 138 | 139 | if module.check_mode: 140 | module.exit_json(changed=True) 141 | 142 | api.delete_route(route_id=resource.id, region=module.params["region"]) 143 | 144 | module.exit_json( 145 | changed=True, 146 | msg=f"lb's route {resource.id} deleted", 147 | ) 148 | 149 | 150 | def core(module: AnsibleModule) -> None: 151 | client = scaleway_get_client_from_module(module) 152 | 153 | state = module.params.pop("state") 154 | scaleway_pop_client_params(module) 155 | scaleway_pop_waitable_resource_params(module) 156 | 157 | if state == "present": 158 | create(module, client) 159 | elif state == "absent": 160 | delete(module, client) 161 | 162 | 163 | def main() -> None: 164 | argument_spec = scaleway_argument_spec() 165 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 166 | argument_spec.update( 167 | state=dict(type="str", default="present", choices=["absent", "present"]), 168 | route_id=dict(type="str"), 169 | frontend_id=dict( 170 | type="str", 171 | required=True, 172 | ), 173 | backend_id=dict( 174 | type="str", 175 | required=True, 176 | ), 177 | region=dict( 178 | type="str", 179 | required=False, 180 | choices=["fr-par", "nl-ams", "pl-waw"], 181 | ), 182 | match=dict( 183 | type="dict", 184 | required=False, 185 | ), 186 | ) 187 | 188 | module = AnsibleModule( 189 | argument_spec=argument_spec, 190 | supports_check_mode=True, 191 | ) 192 | 193 | if not HAS_SCALEWAY_SDK: 194 | module.fail_json(msg=missing_required_lib("scaleway")) 195 | 196 | core(module) 197 | 198 | 199 | if __name__ == "__main__": 200 | main() 201 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_vpcgw_dhcp_entry.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_vpcgw_dhcp_entry 13 | short_description: Manage Scaleway vpcgw's dhcp_entry 14 | description: 15 | - This module can be used to manage Scaleway vpcgw's dhcp_entry. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | dhcp_entry_id: 34 | description: dhcp_entry_id 35 | type: str 36 | required: false 37 | gateway_network_id: 38 | description: gateway_network_id 39 | type: str 40 | required: true 41 | mac_address: 42 | description: mac_address 43 | type: str 44 | required: true 45 | ip_address: 46 | description: ip_address 47 | type: str 48 | required: true 49 | zone: 50 | description: zone 51 | type: str 52 | required: false 53 | """ 54 | 55 | EXAMPLES = r""" 56 | - name: Create a dhcp_entry 57 | scaleway.scaleway.scaleway_vpcgw_dhcp_entry: 58 | access_key: "{{ scw_access_key }}" 59 | secret_key: "{{ scw_secret_key }}" 60 | gateway_network_id: "aaaaaa" 61 | mac_address: "aaaaaa" 62 | ip_address: "aaaaaa" 63 | """ 64 | 65 | RETURN = r""" 66 | --- 67 | dhcp_entry: 68 | description: The dhcp_entry information 69 | returned: when I(state=present) 70 | type: dict 71 | sample: 72 | id: 00000000-0000-0000-0000-000000000000 73 | created_at: "aaaaaa" 74 | updated_at: "aaaaaa" 75 | gateway_network_id: 00000000-0000-0000-0000-000000000000 76 | mac_address: "aaaaaa" 77 | ip_address: "aaaaaa" 78 | hostname: "aaaaaa" 79 | type_: reservation 80 | zone: "aaaaaa" 81 | """ 82 | 83 | from ansible.module_utils.basic import ( 84 | AnsibleModule, 85 | missing_required_lib, 86 | ) 87 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 88 | scaleway_argument_spec, 89 | scaleway_waitable_resource_argument_spec, 90 | scaleway_get_client_from_module, 91 | scaleway_pop_client_params, 92 | scaleway_pop_waitable_resource_params, 93 | ) 94 | 95 | try: 96 | from scaleway import Client 97 | from scaleway.vpcgw.v1 import VpcgwV1API 98 | 99 | HAS_SCALEWAY_SDK = True 100 | except ImportError: 101 | HAS_SCALEWAY_SDK = False 102 | 103 | 104 | def create(module: AnsibleModule, client: "Client") -> None: 105 | api = VpcgwV1API(client) 106 | 107 | id = module.params.pop("id", None) 108 | if id is not None: 109 | resource = api.get_dhcp_entry(dhcp_entry_id=id) 110 | 111 | if module.check_mode: 112 | module.exit_json(changed=False) 113 | 114 | module.exit_json(changed=False, data=resource) 115 | 116 | if module.check_mode: 117 | module.exit_json(changed=True) 118 | 119 | not_none_params = { 120 | key: value for key, value in module.params.items() if value is not None 121 | } 122 | resource = api.create_dhcp_entry(**not_none_params) 123 | 124 | module.exit_json(changed=True, data=resource.__dict__) 125 | 126 | 127 | def delete(module: AnsibleModule, client: "Client") -> None: 128 | api = VpcgwV1API(client) 129 | 130 | id = module.params.pop("id", None) 131 | 132 | if id is not None: 133 | resource = api.get_dhcp_entry(dhcp_entry_id=id, region=module.params["region"]) 134 | else: 135 | module.fail_json(msg="id is required") 136 | 137 | if module.check_mode: 138 | module.exit_json(changed=True) 139 | 140 | api.delete_dhcp_entry(dhcp_entry_id=resource.id, region=module.params["region"]) 141 | 142 | module.exit_json( 143 | changed=True, 144 | msg=f"vpcgw's dhcp_entry {resource.id} deleted", 145 | ) 146 | 147 | 148 | def core(module: AnsibleModule) -> None: 149 | client = scaleway_get_client_from_module(module) 150 | 151 | state = module.params.pop("state") 152 | scaleway_pop_client_params(module) 153 | scaleway_pop_waitable_resource_params(module) 154 | 155 | if state == "present": 156 | create(module, client) 157 | elif state == "absent": 158 | delete(module, client) 159 | 160 | 161 | def main() -> None: 162 | argument_spec = scaleway_argument_spec() 163 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 164 | argument_spec.update( 165 | state=dict(type="str", default="present", choices=["absent", "present"]), 166 | dhcp_entry_id=dict(type="str"), 167 | gateway_network_id=dict( 168 | type="str", 169 | required=True, 170 | ), 171 | mac_address=dict( 172 | type="str", 173 | required=True, 174 | ), 175 | ip_address=dict( 176 | type="str", 177 | required=True, 178 | ), 179 | zone=dict( 180 | type="str", 181 | required=False, 182 | ), 183 | ) 184 | 185 | module = AnsibleModule( 186 | argument_spec=argument_spec, 187 | supports_check_mode=True, 188 | ) 189 | 190 | if not HAS_SCALEWAY_SDK: 191 | module.fail_json(msg=missing_required_lib("scaleway")) 192 | 193 | core(module) 194 | 195 | 196 | if __name__ == "__main__": 197 | main() 198 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_function_domain.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_function_domain 13 | short_description: Manage Scaleway function's domain 14 | description: 15 | - This module can be used to manage Scaleway function's domain. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | domain_id: 34 | description: domain_id 35 | type: str 36 | required: false 37 | hostname: 38 | description: hostname 39 | type: str 40 | required: true 41 | function_id: 42 | description: function_id 43 | type: str 44 | required: true 45 | region: 46 | description: region 47 | type: str 48 | required: false 49 | choices: 50 | - fr-par 51 | - nl-ams 52 | - pl-waw 53 | """ 54 | 55 | EXAMPLES = r""" 56 | - name: Create a domain 57 | scaleway.scaleway.scaleway_function_domain: 58 | access_key: "{{ scw_access_key }}" 59 | secret_key: "{{ scw_secret_key }}" 60 | hostname: "aaaaaa" 61 | function_id: "aaaaaa" 62 | """ 63 | 64 | RETURN = r""" 65 | --- 66 | domain: 67 | description: The domain information 68 | returned: when I(state=present) 69 | type: dict 70 | sample: 71 | id: 00000000-0000-0000-0000-000000000000 72 | hostname: "aaaaaa" 73 | function_id: 00000000-0000-0000-0000-000000000000 74 | url: "aaaaaa" 75 | status: ready 76 | error_message: "aaaaaa" 77 | """ 78 | 79 | from ansible.module_utils.basic import ( 80 | AnsibleModule, 81 | missing_required_lib, 82 | ) 83 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 84 | scaleway_argument_spec, 85 | scaleway_waitable_resource_argument_spec, 86 | scaleway_get_client_from_module, 87 | scaleway_pop_client_params, 88 | scaleway_pop_waitable_resource_params, 89 | ) 90 | 91 | try: 92 | from scaleway import Client, ScalewayException 93 | from scaleway.function.v1beta1 import FunctionV1Beta1API 94 | 95 | HAS_SCALEWAY_SDK = True 96 | except ImportError: 97 | HAS_SCALEWAY_SDK = False 98 | 99 | 100 | def create(module: AnsibleModule, client: "Client") -> None: 101 | api = FunctionV1Beta1API(client) 102 | 103 | id = module.params.pop("id", None) 104 | if id is not None: 105 | resource = api.get_domain(domain_id=id) 106 | 107 | if module.check_mode: 108 | module.exit_json(changed=False) 109 | 110 | module.exit_json(changed=False, data=resource) 111 | 112 | if module.check_mode: 113 | module.exit_json(changed=True) 114 | 115 | not_none_params = { 116 | key: value for key, value in module.params.items() if value is not None 117 | } 118 | resource = api.create_domain(**not_none_params) 119 | resource = api.wait_for_domain( 120 | domain_id=resource.id, region=module.params["region"] 121 | ) 122 | 123 | module.exit_json(changed=True, data=resource.__dict__) 124 | 125 | 126 | def delete(module: AnsibleModule, client: "Client") -> None: 127 | api = FunctionV1Beta1API(client) 128 | 129 | id = module.params.pop("id", None) 130 | 131 | if id is not None: 132 | resource = api.get_domain(domain_id=id, region=module.params["region"]) 133 | else: 134 | module.fail_json(msg="id is required") 135 | 136 | if module.check_mode: 137 | module.exit_json(changed=True) 138 | 139 | api.delete_domain(domain_id=resource.id, region=module.params["region"]) 140 | 141 | try: 142 | api.wait_for_domain(domain_id=resource.id, region=module.params["region"]) 143 | except ScalewayException as e: 144 | if e.status_code != 404: 145 | raise e 146 | 147 | module.exit_json( 148 | changed=True, 149 | msg=f"function's domain {resource.id} deleted", 150 | ) 151 | 152 | 153 | def core(module: AnsibleModule) -> None: 154 | client = scaleway_get_client_from_module(module) 155 | 156 | state = module.params.pop("state") 157 | scaleway_pop_client_params(module) 158 | scaleway_pop_waitable_resource_params(module) 159 | 160 | if state == "present": 161 | create(module, client) 162 | elif state == "absent": 163 | delete(module, client) 164 | 165 | 166 | def main() -> None: 167 | argument_spec = scaleway_argument_spec() 168 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 169 | argument_spec.update( 170 | state=dict(type="str", default="present", choices=["absent", "present"]), 171 | domain_id=dict(type="str"), 172 | hostname=dict( 173 | type="str", 174 | required=True, 175 | ), 176 | function_id=dict( 177 | type="str", 178 | required=True, 179 | ), 180 | region=dict( 181 | type="str", 182 | required=False, 183 | choices=["fr-par", "nl-ams", "pl-waw"], 184 | ), 185 | ) 186 | 187 | module = AnsibleModule( 188 | argument_spec=argument_spec, 189 | supports_check_mode=True, 190 | ) 191 | 192 | if not HAS_SCALEWAY_SDK: 193 | module.fail_json(msg=missing_required_lib("scaleway")) 194 | 195 | core(module) 196 | 197 | 198 | if __name__ == "__main__": 199 | main() 200 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_container_domain.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_container_domain 13 | short_description: Manage Scaleway container's domain 14 | description: 15 | - This module can be used to manage Scaleway container's domain. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | domain_id: 34 | description: domain_id 35 | type: str 36 | required: false 37 | hostname: 38 | description: hostname 39 | type: str 40 | required: true 41 | container_id: 42 | description: container_id 43 | type: str 44 | required: true 45 | region: 46 | description: region 47 | type: str 48 | required: false 49 | choices: 50 | - fr-par 51 | - nl-ams 52 | - pl-waw 53 | """ 54 | 55 | EXAMPLES = r""" 56 | - name: Create a domain 57 | scaleway.scaleway.scaleway_container_domain: 58 | access_key: "{{ scw_access_key }}" 59 | secret_key: "{{ scw_secret_key }}" 60 | hostname: "aaaaaa" 61 | container_id: "aaaaaa" 62 | """ 63 | 64 | RETURN = r""" 65 | --- 66 | domain: 67 | description: The domain information 68 | returned: when I(state=present) 69 | type: dict 70 | sample: 71 | id: 00000000-0000-0000-0000-000000000000 72 | hostname: "aaaaaa" 73 | container_id: 00000000-0000-0000-0000-000000000000 74 | url: "aaaaaa" 75 | status: ready 76 | error_message: "aaaaaa" 77 | """ 78 | 79 | from ansible.module_utils.basic import ( 80 | AnsibleModule, 81 | missing_required_lib, 82 | ) 83 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 84 | scaleway_argument_spec, 85 | scaleway_waitable_resource_argument_spec, 86 | scaleway_get_client_from_module, 87 | scaleway_pop_client_params, 88 | scaleway_pop_waitable_resource_params, 89 | ) 90 | 91 | try: 92 | from scaleway import Client, ScalewayException 93 | from scaleway.container.v1beta1 import ContainerV1Beta1API 94 | 95 | HAS_SCALEWAY_SDK = True 96 | except ImportError: 97 | HAS_SCALEWAY_SDK = False 98 | 99 | 100 | def create(module: AnsibleModule, client: "Client") -> None: 101 | api = ContainerV1Beta1API(client) 102 | 103 | id = module.params.pop("id", None) 104 | if id is not None: 105 | resource = api.get_domain(domain_id=id) 106 | 107 | if module.check_mode: 108 | module.exit_json(changed=False) 109 | 110 | module.exit_json(changed=False, data=resource) 111 | 112 | if module.check_mode: 113 | module.exit_json(changed=True) 114 | 115 | not_none_params = { 116 | key: value for key, value in module.params.items() if value is not None 117 | } 118 | resource = api.create_domain(**not_none_params) 119 | resource = api.wait_for_domain( 120 | domain_id=resource.id, region=module.params["region"] 121 | ) 122 | 123 | module.exit_json(changed=True, data=resource.__dict__) 124 | 125 | 126 | def delete(module: AnsibleModule, client: "Client") -> None: 127 | api = ContainerV1Beta1API(client) 128 | 129 | id = module.params.pop("id", None) 130 | 131 | if id is not None: 132 | resource = api.get_domain(domain_id=id, region=module.params["region"]) 133 | else: 134 | module.fail_json(msg="id is required") 135 | 136 | if module.check_mode: 137 | module.exit_json(changed=True) 138 | 139 | api.delete_domain(domain_id=resource.id, region=module.params["region"]) 140 | 141 | try: 142 | api.wait_for_domain(domain_id=resource.id, region=module.params["region"]) 143 | except ScalewayException as e: 144 | if e.status_code != 404: 145 | raise e 146 | 147 | module.exit_json( 148 | changed=True, 149 | msg=f"container's domain {resource.id} deleted", 150 | ) 151 | 152 | 153 | def core(module: AnsibleModule) -> None: 154 | client = scaleway_get_client_from_module(module) 155 | 156 | state = module.params.pop("state") 157 | scaleway_pop_client_params(module) 158 | scaleway_pop_waitable_resource_params(module) 159 | 160 | if state == "present": 161 | create(module, client) 162 | elif state == "absent": 163 | delete(module, client) 164 | 165 | 166 | def main() -> None: 167 | argument_spec = scaleway_argument_spec() 168 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 169 | argument_spec.update( 170 | state=dict(type="str", default="present", choices=["absent", "present"]), 171 | domain_id=dict(type="str"), 172 | hostname=dict( 173 | type="str", 174 | required=True, 175 | ), 176 | container_id=dict( 177 | type="str", 178 | required=True, 179 | ), 180 | region=dict( 181 | type="str", 182 | required=False, 183 | choices=["fr-par", "nl-ams", "pl-waw"], 184 | ), 185 | ) 186 | 187 | module = AnsibleModule( 188 | argument_spec=argument_spec, 189 | supports_check_mode=True, 190 | ) 191 | 192 | if not HAS_SCALEWAY_SDK: 193 | module.fail_json(msg=missing_required_lib("scaleway")) 194 | 195 | core(module) 196 | 197 | 198 | if __name__ == "__main__": 199 | main() 200 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_account_project.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_account_project 13 | short_description: Manage Scaleway account's project 14 | description: 15 | - This module can be used to manage Scaleway account's project. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | project_id: 34 | description: project_id 35 | type: str 36 | required: false 37 | name: 38 | description: name 39 | type: str 40 | required: true 41 | organization_id: 42 | description: organization_id 43 | type: str 44 | required: false 45 | description: 46 | description: description 47 | type: str 48 | required: false 49 | """ 50 | 51 | EXAMPLES = r""" 52 | - name: Create a project 53 | scaleway.scaleway.scaleway_account_project: 54 | access_key: "{{ scw_access_key }}" 55 | secret_key: "{{ scw_secret_key }}" 56 | name: "aaaaaa" 57 | """ 58 | 59 | RETURN = r""" 60 | --- 61 | project: 62 | description: The project information 63 | returned: when I(state=present) 64 | type: dict 65 | sample: 66 | id: 00000000-0000-0000-0000-000000000000 67 | name: "aaaaaa" 68 | organization_id: 00000000-0000-0000-0000-000000000000 69 | created_at: "aaaaaa" 70 | updated_at: "aaaaaa" 71 | description: "aaaaaa" 72 | """ 73 | 74 | from ansible.module_utils.basic import ( 75 | AnsibleModule, 76 | missing_required_lib, 77 | ) 78 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 79 | scaleway_argument_spec, 80 | scaleway_waitable_resource_argument_spec, 81 | scaleway_get_client_from_module, 82 | scaleway_pop_client_params, 83 | scaleway_pop_waitable_resource_params, 84 | ) 85 | 86 | try: 87 | from scaleway import Client 88 | from scaleway.account.v3 import AccountV3ProjectAPI 89 | 90 | HAS_SCALEWAY_SDK = True 91 | except ImportError: 92 | HAS_SCALEWAY_SDK = False 93 | 94 | 95 | def create(module: AnsibleModule, client: "Client") -> None: 96 | api = AccountV3ProjectAPI(client) 97 | 98 | id = module.params.pop("id", None) 99 | if id is not None: 100 | resource = api.get_project(project_id=id) 101 | 102 | if module.check_mode: 103 | module.exit_json(changed=False) 104 | 105 | module.exit_json(changed=False, data=resource) 106 | 107 | if module.check_mode: 108 | module.exit_json(changed=True) 109 | 110 | not_none_params = { 111 | key: value for key, value in module.params.items() if value is not None 112 | } 113 | resource = api.create_project(**not_none_params) 114 | 115 | module.exit_json(changed=True, data=resource.__dict__) 116 | 117 | 118 | def delete(module: AnsibleModule, client: "Client") -> None: 119 | api = AccountV3ProjectAPI(client) 120 | 121 | id = module.params.pop("id", None) 122 | name = module.params.pop("name", None) 123 | 124 | if id is not None: 125 | resource = api.get_project(project_id=id, region=module.params["region"]) 126 | elif name is not None: 127 | resources = api.list_projects_all(name=name, region=module.params["region"]) 128 | if len(resources) == 0: 129 | module.exit_json(msg="No project found with name {name}") 130 | elif len(resources) > 1: 131 | module.exit_json(msg="More than one project found with name {name}") 132 | else: 133 | resource = resources[0] 134 | else: 135 | module.fail_json(msg="id is required") 136 | 137 | if module.check_mode: 138 | module.exit_json(changed=True) 139 | 140 | api.delete_project(project_id=resource.id, region=module.params["region"]) 141 | 142 | module.exit_json( 143 | changed=True, 144 | msg=f"account's project {resource.name} ({resource.id}) deleted", 145 | ) 146 | 147 | 148 | def core(module: AnsibleModule) -> None: 149 | client = scaleway_get_client_from_module(module) 150 | 151 | state = module.params.pop("state") 152 | scaleway_pop_client_params(module) 153 | scaleway_pop_waitable_resource_params(module) 154 | 155 | if state == "present": 156 | create(module, client) 157 | elif state == "absent": 158 | delete(module, client) 159 | 160 | 161 | def main() -> None: 162 | argument_spec = scaleway_argument_spec() 163 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 164 | argument_spec.update( 165 | state=dict(type="str", default="present", choices=["absent", "present"]), 166 | project_id=dict(type="str"), 167 | name=dict( 168 | type="str", 169 | required=True, 170 | ), 171 | organization_id=dict( 172 | type="str", 173 | required=False, 174 | ), 175 | description=dict( 176 | type="str", 177 | required=False, 178 | ), 179 | ) 180 | 181 | module = AnsibleModule( 182 | argument_spec=argument_spec, 183 | required_one_of=(["project_id", "name"],), 184 | supports_check_mode=True, 185 | ) 186 | 187 | if not HAS_SCALEWAY_SDK: 188 | module.fail_json(msg=missing_required_lib("scaleway")) 189 | 190 | core(module) 191 | 192 | 193 | if __name__ == "__main__": 194 | main() 195 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_iam_group.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_iam_group 13 | short_description: Manage Scaleway iam's group 14 | description: 15 | - This module can be used to manage Scaleway iam's group. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | group_id: 34 | description: group_id 35 | type: str 36 | required: false 37 | description: 38 | description: description 39 | type: str 40 | required: true 41 | organization_id: 42 | description: organization_id 43 | type: str 44 | required: false 45 | name: 46 | description: name 47 | type: str 48 | required: false 49 | """ 50 | 51 | EXAMPLES = r""" 52 | - name: Create a group 53 | scaleway.scaleway.scaleway_iam_group: 54 | access_key: "{{ scw_access_key }}" 55 | secret_key: "{{ scw_secret_key }}" 56 | description: "aaaaaa" 57 | """ 58 | 59 | RETURN = r""" 60 | --- 61 | group: 62 | description: The group information 63 | returned: when I(state=present) 64 | type: dict 65 | sample: 66 | id: 00000000-0000-0000-0000-000000000000 67 | created_at: "aaaaaa" 68 | updated_at: "aaaaaa" 69 | organization_id: 00000000-0000-0000-0000-000000000000 70 | name: "aaaaaa" 71 | description: "aaaaaa" 72 | user_ids: 00000000-0000-0000-0000-000000000000 73 | application_ids: 00000000-0000-0000-0000-000000000000 74 | """ 75 | 76 | from ansible.module_utils.basic import ( 77 | AnsibleModule, 78 | missing_required_lib, 79 | ) 80 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 81 | scaleway_argument_spec, 82 | scaleway_waitable_resource_argument_spec, 83 | scaleway_get_client_from_module, 84 | scaleway_pop_client_params, 85 | scaleway_pop_waitable_resource_params, 86 | ) 87 | 88 | try: 89 | from scaleway import Client 90 | from scaleway.iam.v1alpha1 import IamV1Alpha1API 91 | 92 | HAS_SCALEWAY_SDK = True 93 | except ImportError: 94 | HAS_SCALEWAY_SDK = False 95 | 96 | 97 | def create(module: AnsibleModule, client: "Client") -> None: 98 | api = IamV1Alpha1API(client) 99 | 100 | id = module.params.pop("id", None) 101 | if id is not None: 102 | resource = api.get_group(group_id=id) 103 | 104 | if module.check_mode: 105 | module.exit_json(changed=False) 106 | 107 | module.exit_json(changed=False, data=resource) 108 | 109 | if module.check_mode: 110 | module.exit_json(changed=True) 111 | 112 | not_none_params = { 113 | key: value for key, value in module.params.items() if value is not None 114 | } 115 | resource = api.create_group(**not_none_params) 116 | 117 | module.exit_json(changed=True, data=resource.__dict__) 118 | 119 | 120 | def delete(module: AnsibleModule, client: "Client") -> None: 121 | api = IamV1Alpha1API(client) 122 | 123 | id = module.params.pop("id", None) 124 | name = module.params.pop("name", None) 125 | 126 | if id is not None: 127 | resource = api.get_group(group_id=id, region=module.params["region"]) 128 | elif name is not None: 129 | resources = api.list_groups_all(name=name, region=module.params["region"]) 130 | if len(resources) == 0: 131 | module.exit_json(msg="No group found with name {name}") 132 | elif len(resources) > 1: 133 | module.exit_json(msg="More than one group found with name {name}") 134 | else: 135 | resource = resources[0] 136 | else: 137 | module.fail_json(msg="id is required") 138 | 139 | if module.check_mode: 140 | module.exit_json(changed=True) 141 | 142 | api.delete_group(group_id=resource.id, region=module.params["region"]) 143 | 144 | module.exit_json( 145 | changed=True, 146 | msg=f"iam's group {resource.name} ({resource.id}) deleted", 147 | ) 148 | 149 | 150 | def core(module: AnsibleModule) -> None: 151 | client = scaleway_get_client_from_module(module) 152 | 153 | state = module.params.pop("state") 154 | scaleway_pop_client_params(module) 155 | scaleway_pop_waitable_resource_params(module) 156 | 157 | if state == "present": 158 | create(module, client) 159 | elif state == "absent": 160 | delete(module, client) 161 | 162 | 163 | def main() -> None: 164 | argument_spec = scaleway_argument_spec() 165 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 166 | argument_spec.update( 167 | state=dict(type="str", default="present", choices=["absent", "present"]), 168 | group_id=dict(type="str"), 169 | description=dict( 170 | type="str", 171 | required=True, 172 | ), 173 | organization_id=dict( 174 | type="str", 175 | required=False, 176 | ), 177 | name=dict( 178 | type="str", 179 | required=False, 180 | ), 181 | ) 182 | 183 | module = AnsibleModule( 184 | argument_spec=argument_spec, 185 | required_one_of=(["group_id", "name"],), 186 | supports_check_mode=True, 187 | ) 188 | 189 | if not HAS_SCALEWAY_SDK: 190 | module.fail_json(msg=missing_required_lib("scaleway")) 191 | 192 | core(module) 193 | 194 | 195 | if __name__ == "__main__": 196 | main() 197 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_rdb_read_replica.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_rdb_read_replica 13 | short_description: Manage Scaleway rdb's read_replica 14 | description: 15 | - This module can be used to manage Scaleway rdb's read_replica. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | read_replica_id: 34 | description: read_replica_id 35 | type: str 36 | required: false 37 | instance_id: 38 | description: instance_id 39 | type: str 40 | required: true 41 | region: 42 | description: region 43 | type: str 44 | required: false 45 | choices: 46 | - fr-par 47 | - nl-ams 48 | - pl-waw 49 | endpoint_spec: 50 | description: endpoint_spec 51 | type: list 52 | elements: str 53 | required: false 54 | """ 55 | 56 | EXAMPLES = r""" 57 | - name: Create a read_replica 58 | scaleway.scaleway.scaleway_rdb_read_replica: 59 | access_key: "{{ scw_access_key }}" 60 | secret_key: "{{ scw_secret_key }}" 61 | instance_id: "aaaaaa" 62 | """ 63 | 64 | RETURN = r""" 65 | --- 66 | read_replica: 67 | description: The read_replica information 68 | returned: when I(state=present) 69 | type: dict 70 | sample: 71 | id: 00000000-0000-0000-0000-000000000000 72 | endpoints: 73 | - aaaaaa 74 | - bbbbbb 75 | status: provisioning 76 | region: fr-par 77 | """ 78 | 79 | from ansible.module_utils.basic import ( 80 | AnsibleModule, 81 | missing_required_lib, 82 | ) 83 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 84 | scaleway_argument_spec, 85 | scaleway_waitable_resource_argument_spec, 86 | scaleway_get_client_from_module, 87 | scaleway_pop_client_params, 88 | scaleway_pop_waitable_resource_params, 89 | ) 90 | 91 | try: 92 | from scaleway import Client, ScalewayException 93 | from scaleway.rdb.v1 import RdbV1API 94 | 95 | HAS_SCALEWAY_SDK = True 96 | except ImportError: 97 | HAS_SCALEWAY_SDK = False 98 | 99 | 100 | def create(module: AnsibleModule, client: "Client") -> None: 101 | api = RdbV1API(client) 102 | 103 | id = module.params.pop("id", None) 104 | if id is not None: 105 | resource = api.get_read_replica(read_replica_id=id) 106 | 107 | if module.check_mode: 108 | module.exit_json(changed=False) 109 | 110 | module.exit_json(changed=False, data=resource) 111 | 112 | if module.check_mode: 113 | module.exit_json(changed=True) 114 | 115 | not_none_params = { 116 | key: value for key, value in module.params.items() if value is not None 117 | } 118 | resource = api.create_read_replica(**not_none_params) 119 | resource = api.wait_for_read_replica( 120 | read_replica_id=resource.id, region=module.params["region"] 121 | ) 122 | 123 | module.exit_json(changed=True, data=resource.__dict__) 124 | 125 | 126 | def delete(module: AnsibleModule, client: "Client") -> None: 127 | api = RdbV1API(client) 128 | 129 | id = module.params.pop("id", None) 130 | 131 | if id is not None: 132 | resource = api.get_read_replica( 133 | read_replica_id=id, region=module.params["region"] 134 | ) 135 | else: 136 | module.fail_json(msg="id is required") 137 | 138 | if module.check_mode: 139 | module.exit_json(changed=True) 140 | 141 | api.delete_read_replica(read_replica_id=resource.id, region=module.params["region"]) 142 | 143 | try: 144 | api.wait_for_read_replica( 145 | read_replica_id=resource.id, region=module.params["region"] 146 | ) 147 | except ScalewayException as e: 148 | if e.status_code != 404: 149 | raise e 150 | 151 | module.exit_json( 152 | changed=True, 153 | msg=f"rdb's read_replica {resource.id} deleted", 154 | ) 155 | 156 | 157 | def core(module: AnsibleModule) -> None: 158 | client = scaleway_get_client_from_module(module) 159 | 160 | state = module.params.pop("state") 161 | scaleway_pop_client_params(module) 162 | scaleway_pop_waitable_resource_params(module) 163 | 164 | if state == "present": 165 | create(module, client) 166 | elif state == "absent": 167 | delete(module, client) 168 | 169 | 170 | def main() -> None: 171 | argument_spec = scaleway_argument_spec() 172 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 173 | argument_spec.update( 174 | state=dict(type="str", default="present", choices=["absent", "present"]), 175 | read_replica_id=dict(type="str"), 176 | instance_id=dict( 177 | type="str", 178 | required=True, 179 | ), 180 | region=dict( 181 | type="str", 182 | required=False, 183 | choices=["fr-par", "nl-ams", "pl-waw"], 184 | ), 185 | endpoint_spec=dict( 186 | type="list", 187 | required=False, 188 | elements="str", 189 | ), 190 | ) 191 | 192 | module = AnsibleModule( 193 | argument_spec=argument_spec, 194 | supports_check_mode=True, 195 | ) 196 | 197 | if not HAS_SCALEWAY_SDK: 198 | module.fail_json(msg=missing_required_lib("scaleway")) 199 | 200 | core(module) 201 | 202 | 203 | if __name__ == "__main__": 204 | main() 205 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_iam_ssh_key.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_iam_ssh_key 13 | short_description: Manage Scaleway iam's ssh_key 14 | description: 15 | - This module can be used to manage Scaleway iam's ssh_key. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | ssh_key_id: 34 | description: ssh_key_id 35 | type: str 36 | required: false 37 | public_key: 38 | description: public_key 39 | type: str 40 | required: true 41 | name: 42 | description: name 43 | type: str 44 | required: false 45 | project_id: 46 | description: project_id 47 | type: str 48 | required: false 49 | """ 50 | 51 | EXAMPLES = r""" 52 | - name: Create a ssh_key 53 | scaleway.scaleway.scaleway_iam_ssh_key: 54 | access_key: "{{ scw_access_key }}" 55 | secret_key: "{{ scw_secret_key }}" 56 | public_key: "aaaaaa" 57 | """ 58 | 59 | RETURN = r""" 60 | --- 61 | ssh_key: 62 | description: The ssh_key information 63 | returned: when I(state=present) 64 | type: dict 65 | sample: 66 | id: 00000000-0000-0000-0000-000000000000 67 | name: "aaaaaa" 68 | public_key: "aaaaaa" 69 | fingerprint: "aaaaaa" 70 | created_at: "aaaaaa" 71 | updated_at: "aaaaaa" 72 | organization_id: 00000000-0000-0000-0000-000000000000 73 | project_id: 00000000-0000-0000-0000-000000000000 74 | disabled: true 75 | """ 76 | 77 | from ansible.module_utils.basic import ( 78 | AnsibleModule, 79 | missing_required_lib, 80 | ) 81 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 82 | scaleway_argument_spec, 83 | scaleway_waitable_resource_argument_spec, 84 | scaleway_get_client_from_module, 85 | scaleway_pop_client_params, 86 | scaleway_pop_waitable_resource_params, 87 | ) 88 | 89 | try: 90 | from scaleway import Client 91 | from scaleway.iam.v1alpha1 import IamV1Alpha1API 92 | 93 | HAS_SCALEWAY_SDK = True 94 | except ImportError: 95 | HAS_SCALEWAY_SDK = False 96 | 97 | 98 | def create(module: AnsibleModule, client: "Client") -> None: 99 | api = IamV1Alpha1API(client) 100 | 101 | id = module.params.pop("id", None) 102 | if id is not None: 103 | resource = api.get_ssh_key(ssh_key_id=id) 104 | 105 | if module.check_mode: 106 | module.exit_json(changed=False) 107 | 108 | module.exit_json(changed=False, data=resource) 109 | 110 | if module.check_mode: 111 | module.exit_json(changed=True) 112 | 113 | not_none_params = { 114 | key: value for key, value in module.params.items() if value is not None 115 | } 116 | resource = api.create_ssh_key(**not_none_params) 117 | 118 | module.exit_json(changed=True, data=resource.__dict__) 119 | 120 | 121 | def delete(module: AnsibleModule, client: "Client") -> None: 122 | api = IamV1Alpha1API(client) 123 | 124 | id = module.params.pop("id", None) 125 | name = module.params.pop("name", None) 126 | 127 | if id is not None: 128 | resource = api.get_ssh_key(ssh_key_id=id, region=module.params["region"]) 129 | elif name is not None: 130 | resources = api.list_ssh_keys_all(name=name, region=module.params["region"]) 131 | if len(resources) == 0: 132 | module.exit_json(msg="No ssh_key found with name {name}") 133 | elif len(resources) > 1: 134 | module.exit_json(msg="More than one ssh_key found with name {name}") 135 | else: 136 | resource = resources[0] 137 | else: 138 | module.fail_json(msg="id is required") 139 | 140 | if module.check_mode: 141 | module.exit_json(changed=True) 142 | 143 | api.delete_ssh_key(ssh_key_id=resource.id, region=module.params["region"]) 144 | 145 | module.exit_json( 146 | changed=True, 147 | msg=f"iam's ssh_key {resource.name} ({resource.id}) deleted", 148 | ) 149 | 150 | 151 | def core(module: AnsibleModule) -> None: 152 | client = scaleway_get_client_from_module(module) 153 | 154 | state = module.params.pop("state") 155 | scaleway_pop_client_params(module) 156 | scaleway_pop_waitable_resource_params(module) 157 | 158 | if state == "present": 159 | create(module, client) 160 | elif state == "absent": 161 | delete(module, client) 162 | 163 | 164 | def main() -> None: 165 | argument_spec = scaleway_argument_spec() 166 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 167 | argument_spec.update( 168 | state=dict(type="str", default="present", choices=["absent", "present"]), 169 | ssh_key_id=dict(type="str", no_log=True), 170 | public_key=dict( 171 | type="str", 172 | required=True, 173 | no_log=True, 174 | ), 175 | name=dict( 176 | type="str", 177 | required=False, 178 | ), 179 | project_id=dict( 180 | type="str", 181 | required=False, 182 | ), 183 | ) 184 | 185 | module = AnsibleModule( 186 | argument_spec=argument_spec, 187 | required_one_of=(["ssh_key_id", "name"],), 188 | supports_check_mode=True, 189 | ) 190 | 191 | if not HAS_SCALEWAY_SDK: 192 | module.fail_json(msg=missing_required_lib("scaleway")) 193 | 194 | core(module) 195 | 196 | 197 | if __name__ == "__main__": 198 | main() 199 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_iam_application.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_iam_application 13 | short_description: Manage Scaleway iam's application 14 | description: 15 | - This module can be used to manage Scaleway iam's application. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | application_id: 34 | description: application_id 35 | type: str 36 | required: false 37 | description: 38 | description: description 39 | type: str 40 | required: true 41 | name: 42 | description: name 43 | type: str 44 | required: false 45 | organization_id: 46 | description: organization_id 47 | type: str 48 | required: false 49 | """ 50 | 51 | EXAMPLES = r""" 52 | - name: Create a application 53 | scaleway.scaleway.scaleway_iam_application: 54 | access_key: "{{ scw_access_key }}" 55 | secret_key: "{{ scw_secret_key }}" 56 | description: "aaaaaa" 57 | """ 58 | 59 | RETURN = r""" 60 | --- 61 | application: 62 | description: The application information 63 | returned: when I(state=present) 64 | type: dict 65 | sample: 66 | id: 00000000-0000-0000-0000-000000000000 67 | name: "aaaaaa" 68 | description: "aaaaaa" 69 | created_at: "aaaaaa" 70 | updated_at: "aaaaaa" 71 | organization_id: 00000000-0000-0000-0000-000000000000 72 | editable: true 73 | nb_api_keys: 3 74 | """ 75 | 76 | from ansible.module_utils.basic import ( 77 | AnsibleModule, 78 | missing_required_lib, 79 | ) 80 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 81 | scaleway_argument_spec, 82 | scaleway_waitable_resource_argument_spec, 83 | scaleway_get_client_from_module, 84 | scaleway_pop_client_params, 85 | scaleway_pop_waitable_resource_params, 86 | ) 87 | 88 | try: 89 | from scaleway import Client 90 | from scaleway.iam.v1alpha1 import IamV1Alpha1API 91 | 92 | HAS_SCALEWAY_SDK = True 93 | except ImportError: 94 | HAS_SCALEWAY_SDK = False 95 | 96 | 97 | def create(module: AnsibleModule, client: "Client") -> None: 98 | api = IamV1Alpha1API(client) 99 | 100 | id = module.params.pop("id", None) 101 | if id is not None: 102 | resource = api.get_application(application_id=id) 103 | 104 | if module.check_mode: 105 | module.exit_json(changed=False) 106 | 107 | module.exit_json(changed=False, data=resource) 108 | 109 | if module.check_mode: 110 | module.exit_json(changed=True) 111 | 112 | not_none_params = { 113 | key: value for key, value in module.params.items() if value is not None 114 | } 115 | resource = api.create_application(**not_none_params) 116 | 117 | module.exit_json(changed=True, data=resource.__dict__) 118 | 119 | 120 | def delete(module: AnsibleModule, client: "Client") -> None: 121 | api = IamV1Alpha1API(client) 122 | 123 | id = module.params.pop("id", None) 124 | name = module.params.pop("name", None) 125 | 126 | if id is not None: 127 | resource = api.get_application( 128 | application_id=id, region=module.params["region"] 129 | ) 130 | elif name is not None: 131 | resources = api.list_applications_all(name=name, region=module.params["region"]) 132 | if len(resources) == 0: 133 | module.exit_json(msg="No application found with name {name}") 134 | elif len(resources) > 1: 135 | module.exit_json(msg="More than one application found with name {name}") 136 | else: 137 | resource = resources[0] 138 | else: 139 | module.fail_json(msg="id is required") 140 | 141 | if module.check_mode: 142 | module.exit_json(changed=True) 143 | 144 | api.delete_application(application_id=resource.id, region=module.params["region"]) 145 | 146 | module.exit_json( 147 | changed=True, 148 | msg=f"iam's application {resource.name} ({resource.id}) deleted", 149 | ) 150 | 151 | 152 | def core(module: AnsibleModule) -> None: 153 | client = scaleway_get_client_from_module(module) 154 | 155 | state = module.params.pop("state") 156 | scaleway_pop_client_params(module) 157 | scaleway_pop_waitable_resource_params(module) 158 | 159 | if state == "present": 160 | create(module, client) 161 | elif state == "absent": 162 | delete(module, client) 163 | 164 | 165 | def main() -> None: 166 | argument_spec = scaleway_argument_spec() 167 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 168 | argument_spec.update( 169 | state=dict(type="str", default="present", choices=["absent", "present"]), 170 | application_id=dict(type="str"), 171 | description=dict( 172 | type="str", 173 | required=True, 174 | ), 175 | name=dict( 176 | type="str", 177 | required=False, 178 | ), 179 | organization_id=dict( 180 | type="str", 181 | required=False, 182 | ), 183 | ) 184 | 185 | module = AnsibleModule( 186 | argument_spec=argument_spec, 187 | required_one_of=(["application_id", "name"],), 188 | supports_check_mode=True, 189 | ) 190 | 191 | if not HAS_SCALEWAY_SDK: 192 | module.fail_json(msg=missing_required_lib("scaleway")) 193 | 194 | core(module) 195 | 196 | 197 | if __name__ == "__main__": 198 | main() 199 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_iam_api_key.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_iam_api_key 13 | short_description: Manage Scaleway iam's api_key 14 | description: 15 | - This module can be used to manage Scaleway iam's api_key. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | access_key: 34 | description: access_key 35 | type: str 36 | required: false 37 | description: 38 | description: description 39 | type: str 40 | required: true 41 | application_id: 42 | description: application_id 43 | type: str 44 | required: false 45 | user_id: 46 | description: user_id 47 | type: str 48 | required: false 49 | expires_at: 50 | description: expires_at 51 | type: str 52 | required: false 53 | default_project_id: 54 | description: default_project_id 55 | type: str 56 | required: false 57 | """ 58 | 59 | EXAMPLES = r""" 60 | - name: Create a api_key 61 | scaleway.scaleway.scaleway_iam_api_key: 62 | access_key: "{{ scw_access_key }}" 63 | secret_key: "{{ scw_secret_key }}" 64 | description: "aaaaaa" 65 | """ 66 | 67 | RETURN = r""" 68 | --- 69 | api_key: 70 | description: The api_key information 71 | returned: when I(state=present) 72 | type: dict 73 | sample: 74 | access_key: "aaaaaa" 75 | secret_key: "aaaaaa" 76 | application_id: 00000000-0000-0000-0000-000000000000 77 | user_id: 00000000-0000-0000-0000-000000000000 78 | description: "aaaaaa" 79 | created_at: "aaaaaa" 80 | updated_at: "aaaaaa" 81 | expires_at: "aaaaaa" 82 | default_project_id: 00000000-0000-0000-0000-000000000000 83 | editable: true 84 | creation_ip: "aaaaaa" 85 | """ 86 | 87 | from ansible.module_utils.basic import ( 88 | AnsibleModule, 89 | missing_required_lib, 90 | ) 91 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 92 | scaleway_argument_spec, 93 | scaleway_waitable_resource_argument_spec, 94 | scaleway_get_client_from_module, 95 | scaleway_pop_client_params, 96 | scaleway_pop_waitable_resource_params, 97 | ) 98 | 99 | try: 100 | from scaleway import Client 101 | from scaleway.iam.v1alpha1 import IamV1Alpha1API 102 | 103 | HAS_SCALEWAY_SDK = True 104 | except ImportError: 105 | HAS_SCALEWAY_SDK = False 106 | 107 | 108 | def create(module: AnsibleModule, client: "Client") -> None: 109 | api = IamV1Alpha1API(client) 110 | 111 | id = module.params.pop("id", None) 112 | if id is not None: 113 | resource = api.get_api_key(access_key=id) 114 | 115 | if module.check_mode: 116 | module.exit_json(changed=False) 117 | 118 | module.exit_json(changed=False, data=resource) 119 | 120 | if module.check_mode: 121 | module.exit_json(changed=True) 122 | 123 | not_none_params = { 124 | key: value for key, value in module.params.items() if value is not None 125 | } 126 | resource = api.create_api_key(**not_none_params) 127 | 128 | module.exit_json(changed=True, data=resource.__dict__) 129 | 130 | 131 | def delete(module: AnsibleModule, client: "Client") -> None: 132 | api = IamV1Alpha1API(client) 133 | 134 | access_key = module.params.pop("access_key", None) 135 | 136 | if access_key is not None: 137 | resource = api.get_api_key( 138 | access_key=access_key, region=module.params["region"] 139 | ) 140 | else: 141 | module.fail_json(msg="access_key is required") 142 | 143 | if module.check_mode: 144 | module.exit_json(changed=True) 145 | 146 | api.delete_api_key(access_key=resource.access_key, region=module.params["region"]) 147 | 148 | module.exit_json( 149 | changed=True, 150 | msg=f"iam's api_key {resource.access_key} deleted", 151 | ) 152 | 153 | 154 | def core(module: AnsibleModule) -> None: 155 | client = scaleway_get_client_from_module(module) 156 | 157 | state = module.params.pop("state") 158 | scaleway_pop_client_params(module) 159 | scaleway_pop_waitable_resource_params(module) 160 | 161 | if state == "present": 162 | create(module, client) 163 | elif state == "absent": 164 | delete(module, client) 165 | 166 | 167 | def main() -> None: 168 | argument_spec = scaleway_argument_spec() 169 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 170 | argument_spec.update( 171 | state=dict(type="str", default="present", choices=["absent", "present"]), 172 | access_key=dict(type="str", no_log=True), 173 | description=dict( 174 | type="str", 175 | required=True, 176 | ), 177 | application_id=dict( 178 | type="str", 179 | required=False, 180 | ), 181 | user_id=dict( 182 | type="str", 183 | required=False, 184 | ), 185 | expires_at=dict( 186 | type="str", 187 | required=False, 188 | ), 189 | default_project_id=dict( 190 | type="str", 191 | required=False, 192 | ), 193 | ) 194 | 195 | module = AnsibleModule( 196 | argument_spec=argument_spec, 197 | supports_check_mode=True, 198 | ) 199 | 200 | if not HAS_SCALEWAY_SDK: 201 | module.fail_json(msg=missing_required_lib("scaleway")) 202 | 203 | core(module) 204 | 205 | 206 | if __name__ == "__main__": 207 | main() 208 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_rdb_endpoint.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_rdb_endpoint 13 | short_description: Manage Scaleway rdb's endpoint 14 | description: 15 | - This module can be used to manage Scaleway rdb's endpoint. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | endpoint_id: 34 | description: endpoint_id 35 | type: str 36 | required: false 37 | instance_id: 38 | description: instance_id 39 | type: str 40 | required: true 41 | region: 42 | description: region 43 | type: str 44 | required: false 45 | choices: 46 | - fr-par 47 | - nl-ams 48 | - pl-waw 49 | endpoint_spec: 50 | description: endpoint_spec 51 | type: dict 52 | required: false 53 | """ 54 | 55 | EXAMPLES = r""" 56 | - name: Create a endpoint 57 | scaleway.scaleway.scaleway_rdb_endpoint: 58 | access_key: "{{ scw_access_key }}" 59 | secret_key: "{{ scw_secret_key }}" 60 | instance_id: "aaaaaa" 61 | """ 62 | 63 | RETURN = r""" 64 | --- 65 | endpoint: 66 | description: The endpoint information 67 | returned: when I(state=present) 68 | type: dict 69 | sample: 70 | id: 00000000-0000-0000-0000-000000000000 71 | ip: "aaaaaa" 72 | port: 3 73 | name: "aaaaaa" 74 | private_network: 75 | aaaaaa: bbbbbb 76 | cccccc: dddddd 77 | load_balancer: 78 | aaaaaa: bbbbbb 79 | cccccc: dddddd 80 | direct_access: 81 | aaaaaa: bbbbbb 82 | cccccc: dddddd 83 | hostname: "aaaaaa" 84 | """ 85 | 86 | from ansible.module_utils.basic import ( 87 | AnsibleModule, 88 | missing_required_lib, 89 | ) 90 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 91 | scaleway_argument_spec, 92 | scaleway_waitable_resource_argument_spec, 93 | scaleway_get_client_from_module, 94 | scaleway_pop_client_params, 95 | scaleway_pop_waitable_resource_params, 96 | ) 97 | 98 | try: 99 | from scaleway import Client 100 | from scaleway.rdb.v1 import RdbV1API 101 | 102 | HAS_SCALEWAY_SDK = True 103 | except ImportError: 104 | HAS_SCALEWAY_SDK = False 105 | 106 | 107 | def create(module: AnsibleModule, client: "Client") -> None: 108 | api = RdbV1API(client) 109 | 110 | id = module.params.pop("id", None) 111 | if id is not None: 112 | resource = api.get_endpoint(endpoint_id=id) 113 | 114 | if module.check_mode: 115 | module.exit_json(changed=False) 116 | 117 | module.exit_json(changed=False, data=resource) 118 | 119 | if module.check_mode: 120 | module.exit_json(changed=True) 121 | 122 | not_none_params = { 123 | key: value for key, value in module.params.items() if value is not None 124 | } 125 | resource = api.create_endpoint(**not_none_params) 126 | 127 | module.exit_json(changed=True, data=resource.__dict__) 128 | 129 | 130 | def delete(module: AnsibleModule, client: "Client") -> None: 131 | api = RdbV1API(client) 132 | 133 | id = module.params.pop("id", None) 134 | name = module.params.pop("name", None) 135 | 136 | if id is not None: 137 | resource = api.get_endpoint(endpoint_id=id, region=module.params["region"]) 138 | elif name is not None: 139 | resources = api.list_endpoints_all(name=name, region=module.params["region"]) 140 | if len(resources) == 0: 141 | module.exit_json(msg="No endpoint found with name {name}") 142 | elif len(resources) > 1: 143 | module.exit_json(msg="More than one endpoint found with name {name}") 144 | else: 145 | resource = resources[0] 146 | else: 147 | module.fail_json(msg="id is required") 148 | 149 | if module.check_mode: 150 | module.exit_json(changed=True) 151 | 152 | api.delete_endpoint(endpoint_id=resource.id, region=module.params["region"]) 153 | 154 | module.exit_json( 155 | changed=True, 156 | msg=f"rdb's endpoint {resource.name} ({resource.id}) deleted", 157 | ) 158 | 159 | 160 | def core(module: AnsibleModule) -> None: 161 | client = scaleway_get_client_from_module(module) 162 | 163 | state = module.params.pop("state") 164 | scaleway_pop_client_params(module) 165 | scaleway_pop_waitable_resource_params(module) 166 | 167 | if state == "present": 168 | create(module, client) 169 | elif state == "absent": 170 | delete(module, client) 171 | 172 | 173 | def main() -> None: 174 | argument_spec = scaleway_argument_spec() 175 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 176 | argument_spec.update( 177 | state=dict(type="str", default="present", choices=["absent", "present"]), 178 | endpoint_id=dict(type="str"), 179 | instance_id=dict( 180 | type="str", 181 | required=True, 182 | ), 183 | region=dict( 184 | type="str", 185 | required=False, 186 | choices=["fr-par", "nl-ams", "pl-waw"], 187 | ), 188 | endpoint_spec=dict( 189 | type="dict", 190 | required=False, 191 | ), 192 | ) 193 | 194 | module = AnsibleModule( 195 | argument_spec=argument_spec, 196 | supports_check_mode=True, 197 | ) 198 | 199 | if not HAS_SCALEWAY_SDK: 200 | module.fail_json(msg=missing_required_lib("scaleway")) 201 | 202 | core(module) 203 | 204 | 205 | if __name__ == "__main__": 206 | main() 207 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_function_token.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_function_token 13 | short_description: Manage Scaleway function's token 14 | description: 15 | - This module can be used to manage Scaleway function's token. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | token_id: 34 | description: token_id 35 | type: str 36 | required: false 37 | region: 38 | description: region 39 | type: str 40 | required: false 41 | choices: 42 | - fr-par 43 | - nl-ams 44 | - pl-waw 45 | function_id: 46 | description: function_id 47 | type: str 48 | required: false 49 | namespace_id: 50 | description: namespace_id 51 | type: str 52 | required: false 53 | description: 54 | description: description 55 | type: str 56 | required: false 57 | expires_at: 58 | description: expires_at 59 | type: str 60 | required: false 61 | """ 62 | 63 | EXAMPLES = r""" 64 | - name: Create a token 65 | scaleway.scaleway.scaleway_function_token: 66 | access_key: "{{ scw_access_key }}" 67 | secret_key: "{{ scw_secret_key }}" 68 | """ 69 | 70 | RETURN = r""" 71 | --- 72 | token: 73 | description: The token information 74 | returned: when I(state=present) 75 | type: dict 76 | sample: 77 | id: 00000000-0000-0000-0000-000000000000 78 | token: "aaaaaa" 79 | function_id: 00000000-0000-0000-0000-000000000000 80 | namespace_id: 00000000-0000-0000-0000-000000000000 81 | public_key: "aaaaaa" 82 | status: ready 83 | description: "aaaaaa" 84 | expires_at: "aaaaaa" 85 | """ 86 | 87 | from ansible.module_utils.basic import ( 88 | AnsibleModule, 89 | missing_required_lib, 90 | ) 91 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 92 | scaleway_argument_spec, 93 | scaleway_waitable_resource_argument_spec, 94 | scaleway_get_client_from_module, 95 | scaleway_pop_client_params, 96 | scaleway_pop_waitable_resource_params, 97 | ) 98 | 99 | try: 100 | from scaleway import Client, ScalewayException 101 | from scaleway.function.v1beta1 import FunctionV1Beta1API 102 | 103 | HAS_SCALEWAY_SDK = True 104 | except ImportError: 105 | HAS_SCALEWAY_SDK = False 106 | 107 | 108 | def create(module: AnsibleModule, client: "Client") -> None: 109 | api = FunctionV1Beta1API(client) 110 | 111 | id = module.params.pop("id", None) 112 | if id is not None: 113 | resource = api.get_token(token_id=id) 114 | 115 | if module.check_mode: 116 | module.exit_json(changed=False) 117 | 118 | module.exit_json(changed=False, data=resource) 119 | 120 | if module.check_mode: 121 | module.exit_json(changed=True) 122 | 123 | not_none_params = { 124 | key: value for key, value in module.params.items() if value is not None 125 | } 126 | resource = api.create_token(**not_none_params) 127 | resource = api.wait_for_token(token_id=resource.id, region=module.params["region"]) 128 | 129 | module.exit_json(changed=True, data=resource.__dict__) 130 | 131 | 132 | def delete(module: AnsibleModule, client: "Client") -> None: 133 | api = FunctionV1Beta1API(client) 134 | 135 | id = module.params.pop("id", None) 136 | 137 | if id is not None: 138 | resource = api.get_token(token_id=id, region=module.params["region"]) 139 | else: 140 | module.fail_json(msg="id is required") 141 | 142 | if module.check_mode: 143 | module.exit_json(changed=True) 144 | 145 | api.delete_token(token_id=resource.id, region=module.params["region"]) 146 | 147 | try: 148 | api.wait_for_token(token_id=resource.id, region=module.params["region"]) 149 | except ScalewayException as e: 150 | if e.status_code != 404: 151 | raise e 152 | 153 | module.exit_json( 154 | changed=True, 155 | msg=f"function's token {resource.id} deleted", 156 | ) 157 | 158 | 159 | def core(module: AnsibleModule) -> None: 160 | client = scaleway_get_client_from_module(module) 161 | 162 | state = module.params.pop("state") 163 | scaleway_pop_client_params(module) 164 | scaleway_pop_waitable_resource_params(module) 165 | 166 | if state == "present": 167 | create(module, client) 168 | elif state == "absent": 169 | delete(module, client) 170 | 171 | 172 | def main() -> None: 173 | argument_spec = scaleway_argument_spec() 174 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 175 | argument_spec.update( 176 | state=dict(type="str", default="present", choices=["absent", "present"]), 177 | token_id=dict(type="str"), 178 | region=dict( 179 | type="str", 180 | required=False, 181 | choices=["fr-par", "nl-ams", "pl-waw"], 182 | ), 183 | function_id=dict( 184 | type="str", 185 | required=False, 186 | ), 187 | namespace_id=dict( 188 | type="str", 189 | required=False, 190 | ), 191 | description=dict( 192 | type="str", 193 | required=False, 194 | ), 195 | expires_at=dict( 196 | type="str", 197 | required=False, 198 | ), 199 | ) 200 | 201 | module = AnsibleModule( 202 | argument_spec=argument_spec, 203 | supports_check_mode=True, 204 | ) 205 | 206 | if not HAS_SCALEWAY_SDK: 207 | module.fail_json(msg=missing_required_lib("scaleway")) 208 | 209 | core(module) 210 | 211 | 212 | if __name__ == "__main__": 213 | main() 214 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_container_token.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_container_token 13 | short_description: Manage Scaleway container's token 14 | description: 15 | - This module can be used to manage Scaleway container's token. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | token_id: 34 | description: token_id 35 | type: str 36 | required: false 37 | region: 38 | description: region 39 | type: str 40 | required: false 41 | choices: 42 | - fr-par 43 | - nl-ams 44 | - pl-waw 45 | container_id: 46 | description: container_id 47 | type: str 48 | required: false 49 | namespace_id: 50 | description: namespace_id 51 | type: str 52 | required: false 53 | description: 54 | description: description 55 | type: str 56 | required: false 57 | expires_at: 58 | description: expires_at 59 | type: str 60 | required: false 61 | """ 62 | 63 | EXAMPLES = r""" 64 | - name: Create a token 65 | scaleway.scaleway.scaleway_container_token: 66 | access_key: "{{ scw_access_key }}" 67 | secret_key: "{{ scw_secret_key }}" 68 | """ 69 | 70 | RETURN = r""" 71 | --- 72 | token: 73 | description: The token information 74 | returned: when I(state=present) 75 | type: dict 76 | sample: 77 | id: 00000000-0000-0000-0000-000000000000 78 | token: "aaaaaa" 79 | container_id: 00000000-0000-0000-0000-000000000000 80 | namespace_id: 00000000-0000-0000-0000-000000000000 81 | public_key: "aaaaaa" 82 | status: ready 83 | description: "aaaaaa" 84 | expires_at: "aaaaaa" 85 | """ 86 | 87 | from ansible.module_utils.basic import ( 88 | AnsibleModule, 89 | missing_required_lib, 90 | ) 91 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 92 | scaleway_argument_spec, 93 | scaleway_waitable_resource_argument_spec, 94 | scaleway_get_client_from_module, 95 | scaleway_pop_client_params, 96 | scaleway_pop_waitable_resource_params, 97 | ) 98 | 99 | try: 100 | from scaleway import Client, ScalewayException 101 | from scaleway.container.v1beta1 import ContainerV1Beta1API 102 | 103 | HAS_SCALEWAY_SDK = True 104 | except ImportError: 105 | HAS_SCALEWAY_SDK = False 106 | 107 | 108 | def create(module: AnsibleModule, client: "Client") -> None: 109 | api = ContainerV1Beta1API(client) 110 | 111 | id = module.params.pop("id", None) 112 | if id is not None: 113 | resource = api.get_token(token_id=id) 114 | 115 | if module.check_mode: 116 | module.exit_json(changed=False) 117 | 118 | module.exit_json(changed=False, data=resource) 119 | 120 | if module.check_mode: 121 | module.exit_json(changed=True) 122 | 123 | not_none_params = { 124 | key: value for key, value in module.params.items() if value is not None 125 | } 126 | resource = api.create_token(**not_none_params) 127 | resource = api.wait_for_token(token_id=resource.id, region=module.params["region"]) 128 | 129 | module.exit_json(changed=True, data=resource.__dict__) 130 | 131 | 132 | def delete(module: AnsibleModule, client: "Client") -> None: 133 | api = ContainerV1Beta1API(client) 134 | 135 | id = module.params.pop("id", None) 136 | 137 | if id is not None: 138 | resource = api.get_token(token_id=id, region=module.params["region"]) 139 | else: 140 | module.fail_json(msg="id is required") 141 | 142 | if module.check_mode: 143 | module.exit_json(changed=True) 144 | 145 | api.delete_token(token_id=resource.id, region=module.params["region"]) 146 | 147 | try: 148 | api.wait_for_token(token_id=resource.id, region=module.params["region"]) 149 | except ScalewayException as e: 150 | if e.status_code != 404: 151 | raise e 152 | 153 | module.exit_json( 154 | changed=True, 155 | msg=f"container's token {resource.id} deleted", 156 | ) 157 | 158 | 159 | def core(module: AnsibleModule) -> None: 160 | client = scaleway_get_client_from_module(module) 161 | 162 | state = module.params.pop("state") 163 | scaleway_pop_client_params(module) 164 | scaleway_pop_waitable_resource_params(module) 165 | 166 | if state == "present": 167 | create(module, client) 168 | elif state == "absent": 169 | delete(module, client) 170 | 171 | 172 | def main() -> None: 173 | argument_spec = scaleway_argument_spec() 174 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 175 | argument_spec.update( 176 | state=dict(type="str", default="present", choices=["absent", "present"]), 177 | token_id=dict(type="str"), 178 | region=dict( 179 | type="str", 180 | required=False, 181 | choices=["fr-par", "nl-ams", "pl-waw"], 182 | ), 183 | container_id=dict( 184 | type="str", 185 | required=False, 186 | ), 187 | namespace_id=dict( 188 | type="str", 189 | required=False, 190 | ), 191 | description=dict( 192 | type="str", 193 | required=False, 194 | ), 195 | expires_at=dict( 196 | type="str", 197 | required=False, 198 | ), 199 | ) 200 | 201 | module = AnsibleModule( 202 | argument_spec=argument_spec, 203 | supports_check_mode=True, 204 | ) 205 | 206 | if not HAS_SCALEWAY_SDK: 207 | module.fail_json(msg=missing_required_lib("scaleway")) 208 | 209 | core(module) 210 | 211 | 212 | if __name__ == "__main__": 213 | main() 214 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_vpcgw_pat_rule.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_vpcgw_pat_rule 13 | short_description: Manage Scaleway vpcgw's pat_rule 14 | description: 15 | - This module can be used to manage Scaleway vpcgw's pat_rule. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | pat_rule_id: 34 | description: pat_rule_id 35 | type: str 36 | required: false 37 | gateway_id: 38 | description: gateway_id 39 | type: str 40 | required: true 41 | public_port: 42 | description: public_port 43 | type: int 44 | required: true 45 | private_ip: 46 | description: private_ip 47 | type: str 48 | required: true 49 | private_port: 50 | description: private_port 51 | type: int 52 | required: true 53 | protocol: 54 | description: protocol 55 | type: str 56 | required: true 57 | choices: 58 | - unknown 59 | - both 60 | - tcp 61 | - udp 62 | zone: 63 | description: zone 64 | type: str 65 | required: false 66 | """ 67 | 68 | EXAMPLES = r""" 69 | - name: Create a pat_rule 70 | scaleway.scaleway.scaleway_vpcgw_pat_rule: 71 | access_key: "{{ scw_access_key }}" 72 | secret_key: "{{ scw_secret_key }}" 73 | gateway_id: "aaaaaa" 74 | public_port: "aaaaaa" 75 | private_ip: "aaaaaa" 76 | private_port: "aaaaaa" 77 | protocol: "aaaaaa" 78 | """ 79 | 80 | RETURN = r""" 81 | --- 82 | pat_rule: 83 | description: The pat_rule information 84 | returned: when I(state=present) 85 | type: dict 86 | sample: 87 | id: 00000000-0000-0000-0000-000000000000 88 | gateway_id: 00000000-0000-0000-0000-000000000000 89 | created_at: "aaaaaa" 90 | updated_at: "aaaaaa" 91 | public_port: 3 92 | private_ip: "aaaaaa" 93 | private_port: 3 94 | protocol: both 95 | zone: "aaaaaa" 96 | """ 97 | 98 | from ansible.module_utils.basic import ( 99 | AnsibleModule, 100 | missing_required_lib, 101 | ) 102 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 103 | scaleway_argument_spec, 104 | scaleway_waitable_resource_argument_spec, 105 | scaleway_get_client_from_module, 106 | scaleway_pop_client_params, 107 | scaleway_pop_waitable_resource_params, 108 | ) 109 | 110 | try: 111 | from scaleway import Client 112 | from scaleway.vpcgw.v1 import VpcgwV1API 113 | 114 | HAS_SCALEWAY_SDK = True 115 | except ImportError: 116 | HAS_SCALEWAY_SDK = False 117 | 118 | 119 | def create(module: AnsibleModule, client: "Client") -> None: 120 | api = VpcgwV1API(client) 121 | 122 | id = module.params.pop("id", None) 123 | if id is not None: 124 | resource = api.get_pat_rule(pat_rule_id=id) 125 | 126 | if module.check_mode: 127 | module.exit_json(changed=False) 128 | 129 | module.exit_json(changed=False, data=resource) 130 | 131 | if module.check_mode: 132 | module.exit_json(changed=True) 133 | 134 | not_none_params = { 135 | key: value for key, value in module.params.items() if value is not None 136 | } 137 | resource = api.create_pat_rule(**not_none_params) 138 | 139 | module.exit_json(changed=True, data=resource.__dict__) 140 | 141 | 142 | def delete(module: AnsibleModule, client: "Client") -> None: 143 | api = VpcgwV1API(client) 144 | 145 | id = module.params.pop("id", None) 146 | 147 | if id is not None: 148 | resource = api.get_pat_rule(pat_rule_id=id, region=module.params["region"]) 149 | else: 150 | module.fail_json(msg="id is required") 151 | 152 | if module.check_mode: 153 | module.exit_json(changed=True) 154 | 155 | api.delete_pat_rule(pat_rule_id=resource.id, region=module.params["region"]) 156 | 157 | module.exit_json( 158 | changed=True, 159 | msg=f"vpcgw's pat_rule {resource.id} deleted", 160 | ) 161 | 162 | 163 | def core(module: AnsibleModule) -> None: 164 | client = scaleway_get_client_from_module(module) 165 | 166 | state = module.params.pop("state") 167 | scaleway_pop_client_params(module) 168 | scaleway_pop_waitable_resource_params(module) 169 | 170 | if state == "present": 171 | create(module, client) 172 | elif state == "absent": 173 | delete(module, client) 174 | 175 | 176 | def main() -> None: 177 | argument_spec = scaleway_argument_spec() 178 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 179 | argument_spec.update( 180 | state=dict(type="str", default="present", choices=["absent", "present"]), 181 | pat_rule_id=dict(type="str"), 182 | gateway_id=dict( 183 | type="str", 184 | required=True, 185 | ), 186 | public_port=dict( 187 | type="int", 188 | required=True, 189 | ), 190 | private_ip=dict( 191 | type="str", 192 | required=True, 193 | ), 194 | private_port=dict( 195 | type="int", 196 | required=True, 197 | ), 198 | protocol=dict( 199 | type="str", 200 | required=True, 201 | choices=["unknown", "both", "tcp", "udp"], 202 | ), 203 | zone=dict( 204 | type="str", 205 | required=False, 206 | ), 207 | ) 208 | 209 | module = AnsibleModule( 210 | argument_spec=argument_spec, 211 | supports_check_mode=True, 212 | ) 213 | 214 | if not HAS_SCALEWAY_SDK: 215 | module.fail_json(msg=missing_required_lib("scaleway")) 216 | 217 | core(module) 218 | 219 | 220 | if __name__ == "__main__": 221 | main() 222 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_mnq_credential.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_mnq_credential 13 | short_description: Manage Scaleway mnq's credential 14 | description: 15 | - This module can be used to manage Scaleway mnq's credential. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | credential_id: 34 | description: credential_id 35 | type: str 36 | required: false 37 | namespace_id: 38 | description: namespace_id 39 | type: str 40 | required: true 41 | region: 42 | description: region 43 | type: str 44 | required: false 45 | choices: 46 | - fr-par 47 | - nl-ams 48 | - pl-waw 49 | name: 50 | description: name 51 | type: str 52 | required: false 53 | permissions: 54 | description: permissions 55 | type: dict 56 | required: false 57 | """ 58 | 59 | EXAMPLES = r""" 60 | - name: Create a credential 61 | scaleway.scaleway.scaleway_mnq_credential: 62 | access_key: "{{ scw_access_key }}" 63 | secret_key: "{{ scw_secret_key }}" 64 | namespace_id: "aaaaaa" 65 | """ 66 | 67 | RETURN = r""" 68 | --- 69 | credential: 70 | description: The credential information 71 | returned: when I(state=present) 72 | type: dict 73 | sample: 74 | id: 00000000-0000-0000-0000-000000000000 75 | name: "aaaaaa" 76 | namespace_id: 00000000-0000-0000-0000-000000000000 77 | protocol: nats 78 | nats_credentials: 79 | aaaaaa: bbbbbb 80 | cccccc: dddddd 81 | sqs_sns_credentials: 82 | aaaaaa: bbbbbb 83 | cccccc: dddddd 84 | """ 85 | 86 | from ansible.module_utils.basic import ( 87 | AnsibleModule, 88 | missing_required_lib, 89 | ) 90 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 91 | scaleway_argument_spec, 92 | scaleway_waitable_resource_argument_spec, 93 | scaleway_get_client_from_module, 94 | scaleway_pop_client_params, 95 | scaleway_pop_waitable_resource_params, 96 | ) 97 | 98 | try: 99 | from scaleway import Client 100 | from scaleway.mnq.v1alpha1 import MnqV1Alpha1API 101 | 102 | HAS_SCALEWAY_SDK = True 103 | except ImportError: 104 | HAS_SCALEWAY_SDK = False 105 | 106 | 107 | def create(module: AnsibleModule, client: "Client") -> None: 108 | api = MnqV1Alpha1API(client) 109 | 110 | id = module.params.pop("id", None) 111 | if id is not None: 112 | resource = api.get_credential(credential_id=id) 113 | 114 | if module.check_mode: 115 | module.exit_json(changed=False) 116 | 117 | module.exit_json(changed=False, data=resource) 118 | 119 | if module.check_mode: 120 | module.exit_json(changed=True) 121 | 122 | not_none_params = { 123 | key: value for key, value in module.params.items() if value is not None 124 | } 125 | resource = api.create_credential(**not_none_params) 126 | 127 | module.exit_json(changed=True, data=resource.__dict__) 128 | 129 | 130 | def delete(module: AnsibleModule, client: "Client") -> None: 131 | api = MnqV1Alpha1API(client) 132 | 133 | id = module.params.pop("id", None) 134 | name = module.params.pop("name", None) 135 | 136 | if id is not None: 137 | resource = api.get_credential(credential_id=id, region=module.params["region"]) 138 | elif name is not None: 139 | resources = api.list_credentials_all(name=name, region=module.params["region"]) 140 | if len(resources) == 0: 141 | module.exit_json(msg="No credential found with name {name}") 142 | elif len(resources) > 1: 143 | module.exit_json(msg="More than one credential found with name {name}") 144 | else: 145 | resource = resources[0] 146 | else: 147 | module.fail_json(msg="id is required") 148 | 149 | if module.check_mode: 150 | module.exit_json(changed=True) 151 | 152 | api.delete_credential(credential_id=resource.id, region=module.params["region"]) 153 | 154 | module.exit_json( 155 | changed=True, 156 | msg=f"mnq's credential {resource.name} ({resource.id}) deleted", 157 | ) 158 | 159 | 160 | def core(module: AnsibleModule) -> None: 161 | client = scaleway_get_client_from_module(module) 162 | 163 | state = module.params.pop("state") 164 | scaleway_pop_client_params(module) 165 | scaleway_pop_waitable_resource_params(module) 166 | 167 | if state == "present": 168 | create(module, client) 169 | elif state == "absent": 170 | delete(module, client) 171 | 172 | 173 | def main() -> None: 174 | argument_spec = scaleway_argument_spec() 175 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 176 | argument_spec.update( 177 | state=dict(type="str", default="present", choices=["absent", "present"]), 178 | credential_id=dict(type="str"), 179 | namespace_id=dict( 180 | type="str", 181 | required=True, 182 | ), 183 | region=dict( 184 | type="str", 185 | required=False, 186 | choices=["fr-par", "nl-ams", "pl-waw"], 187 | ), 188 | name=dict( 189 | type="str", 190 | required=False, 191 | ), 192 | permissions=dict( 193 | type="dict", 194 | required=False, 195 | ), 196 | ) 197 | 198 | module = AnsibleModule( 199 | argument_spec=argument_spec, 200 | required_one_of=(["credential_id", "name"],), 201 | supports_check_mode=True, 202 | ) 203 | 204 | if not HAS_SCALEWAY_SDK: 205 | module.fail_json(msg=missing_required_lib("scaleway")) 206 | 207 | core(module) 208 | 209 | 210 | if __name__ == "__main__": 211 | main() 212 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_mnq_namespace.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_mnq_namespace 13 | short_description: Manage Scaleway mnq's namespace 14 | description: 15 | - This module can be used to manage Scaleway mnq's namespace. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | namespace_id: 34 | description: namespace_id 35 | type: str 36 | required: false 37 | region: 38 | description: region 39 | type: str 40 | required: false 41 | choices: 42 | - fr-par 43 | - nl-ams 44 | - pl-waw 45 | name: 46 | description: name 47 | type: str 48 | required: false 49 | protocol: 50 | description: protocol 51 | type: str 52 | required: true 53 | choices: 54 | - unknown 55 | - nats 56 | - sqs_sns 57 | project_id: 58 | description: project_id 59 | type: str 60 | required: false 61 | """ 62 | 63 | EXAMPLES = r""" 64 | - name: Create a namespace 65 | scaleway.scaleway.scaleway_mnq_namespace: 66 | access_key: "{{ scw_access_key }}" 67 | secret_key: "{{ scw_secret_key }}" 68 | protocol: "aaaaaa" 69 | """ 70 | 71 | RETURN = r""" 72 | --- 73 | namespace: 74 | description: The namespace information 75 | returned: when I(state=present) 76 | type: dict 77 | sample: 78 | id: 00000000-0000-0000-0000-000000000000 79 | name: "aaaaaa" 80 | endpoint: "aaaaaa" 81 | protocol: nats 82 | project_id: 00000000-0000-0000-0000-000000000000 83 | region: fr-par 84 | created_at: "aaaaaa" 85 | updated_at: "aaaaaa" 86 | """ 87 | 88 | from ansible.module_utils.basic import ( 89 | AnsibleModule, 90 | missing_required_lib, 91 | ) 92 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 93 | scaleway_argument_spec, 94 | scaleway_waitable_resource_argument_spec, 95 | scaleway_get_client_from_module, 96 | scaleway_pop_client_params, 97 | scaleway_pop_waitable_resource_params, 98 | ) 99 | 100 | try: 101 | from scaleway import Client 102 | from scaleway.mnq.v1alpha1 import MnqV1Alpha1API 103 | 104 | HAS_SCALEWAY_SDK = True 105 | except ImportError: 106 | HAS_SCALEWAY_SDK = False 107 | 108 | 109 | def create(module: AnsibleModule, client: "Client") -> None: 110 | api = MnqV1Alpha1API(client) 111 | 112 | id = module.params.pop("id", None) 113 | if id is not None: 114 | resource = api.get_namespace(namespace_id=id) 115 | 116 | if module.check_mode: 117 | module.exit_json(changed=False) 118 | 119 | module.exit_json(changed=False, data=resource) 120 | 121 | if module.check_mode: 122 | module.exit_json(changed=True) 123 | 124 | not_none_params = { 125 | key: value for key, value in module.params.items() if value is not None 126 | } 127 | resource = api.create_namespace(**not_none_params) 128 | 129 | module.exit_json(changed=True, data=resource.__dict__) 130 | 131 | 132 | def delete(module: AnsibleModule, client: "Client") -> None: 133 | api = MnqV1Alpha1API(client) 134 | 135 | id = module.params.pop("id", None) 136 | name = module.params.pop("name", None) 137 | 138 | if id is not None: 139 | resource = api.get_namespace(namespace_id=id, region=module.params["region"]) 140 | elif name is not None: 141 | resources = api.list_namespaces_all(name=name, region=module.params["region"]) 142 | if len(resources) == 0: 143 | module.exit_json(msg="No namespace found with name {name}") 144 | elif len(resources) > 1: 145 | module.exit_json(msg="More than one namespace found with name {name}") 146 | else: 147 | resource = resources[0] 148 | else: 149 | module.fail_json(msg="id is required") 150 | 151 | if module.check_mode: 152 | module.exit_json(changed=True) 153 | 154 | api.delete_namespace(namespace_id=resource.id, region=module.params["region"]) 155 | 156 | module.exit_json( 157 | changed=True, 158 | msg=f"mnq's namespace {resource.name} ({resource.id}) deleted", 159 | ) 160 | 161 | 162 | def core(module: AnsibleModule) -> None: 163 | client = scaleway_get_client_from_module(module) 164 | 165 | state = module.params.pop("state") 166 | scaleway_pop_client_params(module) 167 | scaleway_pop_waitable_resource_params(module) 168 | 169 | if state == "present": 170 | create(module, client) 171 | elif state == "absent": 172 | delete(module, client) 173 | 174 | 175 | def main() -> None: 176 | argument_spec = scaleway_argument_spec() 177 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 178 | argument_spec.update( 179 | state=dict(type="str", default="present", choices=["absent", "present"]), 180 | namespace_id=dict(type="str"), 181 | region=dict( 182 | type="str", 183 | required=False, 184 | choices=["fr-par", "nl-ams", "pl-waw"], 185 | ), 186 | name=dict( 187 | type="str", 188 | required=False, 189 | ), 190 | protocol=dict( 191 | type="str", 192 | required=True, 193 | choices=["unknown", "nats", "sqs_sns"], 194 | ), 195 | project_id=dict( 196 | type="str", 197 | required=False, 198 | ), 199 | ) 200 | 201 | module = AnsibleModule( 202 | argument_spec=argument_spec, 203 | required_one_of=(["namespace_id", "name"],), 204 | supports_check_mode=True, 205 | ) 206 | 207 | if not HAS_SCALEWAY_SDK: 208 | module.fail_json(msg=missing_required_lib("scaleway")) 209 | 210 | core(module) 211 | 212 | 213 | if __name__ == "__main__": 214 | main() 215 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_iot_network.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_iot_network 13 | short_description: Manage Scaleway iot's network 14 | description: 15 | - This module can be used to manage Scaleway iot's network. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | network_id: 34 | description: network_id 35 | type: str 36 | required: false 37 | hub_id: 38 | description: hub_id 39 | type: str 40 | required: true 41 | topic_prefix: 42 | description: topic_prefix 43 | type: str 44 | required: true 45 | region: 46 | description: region 47 | type: str 48 | required: false 49 | choices: 50 | - fr-par 51 | - nl-ams 52 | - pl-waw 53 | name: 54 | description: name 55 | type: str 56 | required: false 57 | type_: 58 | description: type_ 59 | type: str 60 | required: true 61 | choices: 62 | - unknown 63 | - sigfox 64 | - rest 65 | """ 66 | 67 | EXAMPLES = r""" 68 | - name: Create a network 69 | scaleway.scaleway.scaleway_iot_network: 70 | access_key: "{{ scw_access_key }}" 71 | secret_key: "{{ scw_secret_key }}" 72 | hub_id: "aaaaaa" 73 | topic_prefix: "aaaaaa" 74 | type_: "aaaaaa" 75 | """ 76 | 77 | RETURN = r""" 78 | --- 79 | network: 80 | description: The network information 81 | returned: when I(state=present) 82 | type: dict 83 | sample: 84 | id: 00000000-0000-0000-0000-000000000000 85 | name: "aaaaaa" 86 | type_: sigfox 87 | endpoint: "aaaaaa" 88 | hub_id: 00000000-0000-0000-0000-000000000000 89 | created_at: "aaaaaa" 90 | topic_prefix: "aaaaaa" 91 | """ 92 | 93 | from ansible.module_utils.basic import ( 94 | AnsibleModule, 95 | missing_required_lib, 96 | ) 97 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 98 | scaleway_argument_spec, 99 | scaleway_waitable_resource_argument_spec, 100 | scaleway_get_client_from_module, 101 | scaleway_pop_client_params, 102 | scaleway_pop_waitable_resource_params, 103 | ) 104 | 105 | try: 106 | from scaleway import Client 107 | from scaleway.iot.v1 import IotV1API 108 | 109 | HAS_SCALEWAY_SDK = True 110 | except ImportError: 111 | HAS_SCALEWAY_SDK = False 112 | 113 | 114 | def create(module: AnsibleModule, client: "Client") -> None: 115 | api = IotV1API(client) 116 | 117 | id = module.params.pop("id", None) 118 | if id is not None: 119 | resource = api.get_network(network_id=id) 120 | 121 | if module.check_mode: 122 | module.exit_json(changed=False) 123 | 124 | module.exit_json(changed=False, data=resource) 125 | 126 | if module.check_mode: 127 | module.exit_json(changed=True) 128 | 129 | not_none_params = { 130 | key: value for key, value in module.params.items() if value is not None 131 | } 132 | resource = api.create_network(**not_none_params) 133 | 134 | module.exit_json(changed=True, data=resource.__dict__) 135 | 136 | 137 | def delete(module: AnsibleModule, client: "Client") -> None: 138 | api = IotV1API(client) 139 | 140 | id = module.params.pop("id", None) 141 | name = module.params.pop("name", None) 142 | 143 | if id is not None: 144 | resource = api.get_network(network_id=id, region=module.params["region"]) 145 | elif name is not None: 146 | resources = api.list_networks_all(name=name, region=module.params["region"]) 147 | if len(resources) == 0: 148 | module.exit_json(msg="No network found with name {name}") 149 | elif len(resources) > 1: 150 | module.exit_json(msg="More than one network found with name {name}") 151 | else: 152 | resource = resources[0] 153 | else: 154 | module.fail_json(msg="id is required") 155 | 156 | if module.check_mode: 157 | module.exit_json(changed=True) 158 | 159 | api.delete_network(network_id=resource.id, region=module.params["region"]) 160 | 161 | module.exit_json( 162 | changed=True, 163 | msg=f"iot's network {resource.name} ({resource.id}) deleted", 164 | ) 165 | 166 | 167 | def core(module: AnsibleModule) -> None: 168 | client = scaleway_get_client_from_module(module) 169 | 170 | state = module.params.pop("state") 171 | scaleway_pop_client_params(module) 172 | scaleway_pop_waitable_resource_params(module) 173 | 174 | if state == "present": 175 | create(module, client) 176 | elif state == "absent": 177 | delete(module, client) 178 | 179 | 180 | def main() -> None: 181 | argument_spec = scaleway_argument_spec() 182 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 183 | argument_spec.update( 184 | state=dict(type="str", default="present", choices=["absent", "present"]), 185 | network_id=dict(type="str"), 186 | hub_id=dict( 187 | type="str", 188 | required=True, 189 | ), 190 | topic_prefix=dict( 191 | type="str", 192 | required=True, 193 | ), 194 | region=dict( 195 | type="str", 196 | required=False, 197 | choices=["fr-par", "nl-ams", "pl-waw"], 198 | ), 199 | name=dict( 200 | type="str", 201 | required=False, 202 | ), 203 | type_=dict( 204 | type="str", 205 | required=True, 206 | choices=["unknown", "sigfox", "rest"], 207 | ), 208 | ) 209 | 210 | module = AnsibleModule( 211 | argument_spec=argument_spec, 212 | required_one_of=(["network_id", "name"],), 213 | supports_check_mode=True, 214 | ) 215 | 216 | if not HAS_SCALEWAY_SDK: 217 | module.fail_json(msg=missing_required_lib("scaleway")) 218 | 219 | core(module) 220 | 221 | 222 | if __name__ == "__main__": 223 | main() 224 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_rdb_snapshot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_rdb_snapshot 13 | short_description: Manage Scaleway rdb's snapshot 14 | description: 15 | - This module can be used to manage Scaleway rdb's snapshot. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | snapshot_id: 34 | description: snapshot_id 35 | type: str 36 | required: false 37 | instance_id: 38 | description: instance_id 39 | type: str 40 | required: true 41 | region: 42 | description: region 43 | type: str 44 | required: false 45 | choices: 46 | - fr-par 47 | - nl-ams 48 | - pl-waw 49 | name: 50 | description: name 51 | type: str 52 | required: false 53 | expires_at: 54 | description: expires_at 55 | type: str 56 | required: false 57 | """ 58 | 59 | EXAMPLES = r""" 60 | - name: Create a snapshot 61 | scaleway.scaleway.scaleway_rdb_snapshot: 62 | access_key: "{{ scw_access_key }}" 63 | secret_key: "{{ scw_secret_key }}" 64 | instance_id: "aaaaaa" 65 | """ 66 | 67 | RETURN = r""" 68 | --- 69 | snapshot: 70 | description: The snapshot information 71 | returned: when I(state=present) 72 | type: dict 73 | sample: 74 | id: 00000000-0000-0000-0000-000000000000 75 | instance_id: 00000000-0000-0000-0000-000000000000 76 | name: "aaaaaa" 77 | status: creating 78 | size: 3 79 | expires_at: "aaaaaa" 80 | created_at: "aaaaaa" 81 | updated_at: "aaaaaa" 82 | instance_name: "aaaaaa" 83 | node_type: "aaaaaa" 84 | region: fr-par 85 | """ 86 | 87 | from ansible.module_utils.basic import ( 88 | AnsibleModule, 89 | missing_required_lib, 90 | ) 91 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 92 | scaleway_argument_spec, 93 | scaleway_waitable_resource_argument_spec, 94 | scaleway_get_client_from_module, 95 | scaleway_pop_client_params, 96 | scaleway_pop_waitable_resource_params, 97 | ) 98 | 99 | try: 100 | from scaleway import Client, ScalewayException 101 | from scaleway.rdb.v1 import RdbV1API 102 | 103 | HAS_SCALEWAY_SDK = True 104 | except ImportError: 105 | HAS_SCALEWAY_SDK = False 106 | 107 | 108 | def create(module: AnsibleModule, client: "Client") -> None: 109 | api = RdbV1API(client) 110 | 111 | id = module.params.pop("id", None) 112 | if id is not None: 113 | resource = api.get_snapshot(snapshot_id=id) 114 | 115 | if module.check_mode: 116 | module.exit_json(changed=False) 117 | 118 | module.exit_json(changed=False, data=resource) 119 | 120 | if module.check_mode: 121 | module.exit_json(changed=True) 122 | 123 | not_none_params = { 124 | key: value for key, value in module.params.items() if value is not None 125 | } 126 | resource = api.create_snapshot(**not_none_params) 127 | resource = api.wait_for_snapshot( 128 | snapshot_id=resource.id, region=module.params["region"] 129 | ) 130 | 131 | module.exit_json(changed=True, data=resource.__dict__) 132 | 133 | 134 | def delete(module: AnsibleModule, client: "Client") -> None: 135 | api = RdbV1API(client) 136 | 137 | id = module.params.pop("id", None) 138 | name = module.params.pop("name", None) 139 | 140 | if id is not None: 141 | resource = api.get_snapshot(snapshot_id=id, region=module.params["region"]) 142 | elif name is not None: 143 | resources = api.list_snapshots_all(name=name, region=module.params["region"]) 144 | if len(resources) == 0: 145 | module.exit_json(msg="No snapshot found with name {name}") 146 | elif len(resources) > 1: 147 | module.exit_json(msg="More than one snapshot found with name {name}") 148 | else: 149 | resource = resources[0] 150 | else: 151 | module.fail_json(msg="id is required") 152 | 153 | if module.check_mode: 154 | module.exit_json(changed=True) 155 | 156 | api.delete_snapshot(snapshot_id=resource.id, region=module.params["region"]) 157 | 158 | try: 159 | api.wait_for_snapshot(snapshot_id=resource.id, region=module.params["region"]) 160 | except ScalewayException as e: 161 | if e.status_code != 404: 162 | raise e 163 | 164 | module.exit_json( 165 | changed=True, 166 | msg=f"rdb's snapshot {resource.name} ({resource.id}) deleted", 167 | ) 168 | 169 | 170 | def core(module: AnsibleModule) -> None: 171 | client = scaleway_get_client_from_module(module) 172 | 173 | state = module.params.pop("state") 174 | scaleway_pop_client_params(module) 175 | scaleway_pop_waitable_resource_params(module) 176 | 177 | if state == "present": 178 | create(module, client) 179 | elif state == "absent": 180 | delete(module, client) 181 | 182 | 183 | def main() -> None: 184 | argument_spec = scaleway_argument_spec() 185 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 186 | argument_spec.update( 187 | state=dict(type="str", default="present", choices=["absent", "present"]), 188 | snapshot_id=dict(type="str"), 189 | instance_id=dict( 190 | type="str", 191 | required=True, 192 | ), 193 | region=dict( 194 | type="str", 195 | required=False, 196 | choices=["fr-par", "nl-ams", "pl-waw"], 197 | ), 198 | name=dict( 199 | type="str", 200 | required=False, 201 | ), 202 | expires_at=dict( 203 | type="str", 204 | required=False, 205 | ), 206 | ) 207 | 208 | module = AnsibleModule( 209 | argument_spec=argument_spec, 210 | required_one_of=(["snapshot_id", "name"],), 211 | supports_check_mode=True, 212 | ) 213 | 214 | if not HAS_SCALEWAY_SDK: 215 | module.fail_json(msg=missing_required_lib("scaleway")) 216 | 217 | core(module) 218 | 219 | 220 | if __name__ == "__main__": 221 | main() 222 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_lb_subscriber.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_lb_subscriber 13 | short_description: Manage Scaleway lb's subscriber 14 | description: 15 | - This module can be used to manage Scaleway lb's subscriber. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | subscriber_id: 34 | description: subscriber_id 35 | type: str 36 | required: false 37 | name: 38 | description: name 39 | type: str 40 | required: true 41 | region: 42 | description: region 43 | type: str 44 | required: false 45 | choices: 46 | - fr-par 47 | - nl-ams 48 | - pl-waw 49 | email_config: 50 | description: email_config 51 | type: dict 52 | required: false 53 | webhook_config: 54 | description: webhook_config 55 | type: dict 56 | required: false 57 | organization_id: 58 | description: organization_id 59 | type: str 60 | required: false 61 | project_id: 62 | description: project_id 63 | type: str 64 | required: false 65 | """ 66 | 67 | EXAMPLES = r""" 68 | - name: Create a subscriber 69 | scaleway.scaleway.scaleway_lb_subscriber: 70 | access_key: "{{ scw_access_key }}" 71 | secret_key: "{{ scw_secret_key }}" 72 | name: "aaaaaa" 73 | """ 74 | 75 | RETURN = r""" 76 | --- 77 | subscriber: 78 | description: The subscriber information 79 | returned: when I(state=present) 80 | type: dict 81 | sample: 82 | id: 00000000-0000-0000-0000-000000000000 83 | name: "aaaaaa" 84 | email_config: 85 | aaaaaa: bbbbbb 86 | cccccc: dddddd 87 | webhook_config: 88 | aaaaaa: bbbbbb 89 | cccccc: dddddd 90 | """ 91 | 92 | from ansible.module_utils.basic import ( 93 | AnsibleModule, 94 | missing_required_lib, 95 | ) 96 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 97 | scaleway_argument_spec, 98 | scaleway_waitable_resource_argument_spec, 99 | scaleway_get_client_from_module, 100 | scaleway_pop_client_params, 101 | scaleway_pop_waitable_resource_params, 102 | ) 103 | 104 | try: 105 | from scaleway import Client 106 | from scaleway.lb.v1 import LbV1API 107 | 108 | HAS_SCALEWAY_SDK = True 109 | except ImportError: 110 | HAS_SCALEWAY_SDK = False 111 | 112 | 113 | def create(module: AnsibleModule, client: "Client") -> None: 114 | api = LbV1API(client) 115 | 116 | id = module.params.pop("id", None) 117 | if id is not None: 118 | resource = api.get_subscriber(subscriber_id=id) 119 | 120 | if module.check_mode: 121 | module.exit_json(changed=False) 122 | 123 | module.exit_json(changed=False, data=resource) 124 | 125 | if module.check_mode: 126 | module.exit_json(changed=True) 127 | 128 | not_none_params = { 129 | key: value for key, value in module.params.items() if value is not None 130 | } 131 | resource = api.create_subscriber(**not_none_params) 132 | 133 | module.exit_json(changed=True, data=resource.__dict__) 134 | 135 | 136 | def delete(module: AnsibleModule, client: "Client") -> None: 137 | api = LbV1API(client) 138 | 139 | id = module.params.pop("id", None) 140 | name = module.params.pop("name", None) 141 | 142 | if id is not None: 143 | resource = api.get_subscriber(subscriber_id=id, region=module.params["region"]) 144 | elif name is not None: 145 | resources = api.list_subscribers_all(name=name, region=module.params["region"]) 146 | if len(resources) == 0: 147 | module.exit_json(msg="No subscriber found with name {name}") 148 | elif len(resources) > 1: 149 | module.exit_json(msg="More than one subscriber found with name {name}") 150 | else: 151 | resource = resources[0] 152 | else: 153 | module.fail_json(msg="id is required") 154 | 155 | if module.check_mode: 156 | module.exit_json(changed=True) 157 | 158 | api.delete_subscriber(subscriber_id=resource.id, region=module.params["region"]) 159 | 160 | module.exit_json( 161 | changed=True, 162 | msg=f"lb's subscriber {resource.name} ({resource.id}) deleted", 163 | ) 164 | 165 | 166 | def core(module: AnsibleModule) -> None: 167 | client = scaleway_get_client_from_module(module) 168 | 169 | state = module.params.pop("state") 170 | scaleway_pop_client_params(module) 171 | scaleway_pop_waitable_resource_params(module) 172 | 173 | if state == "present": 174 | create(module, client) 175 | elif state == "absent": 176 | delete(module, client) 177 | 178 | 179 | def main() -> None: 180 | argument_spec = scaleway_argument_spec() 181 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 182 | argument_spec.update( 183 | state=dict(type="str", default="present", choices=["absent", "present"]), 184 | subscriber_id=dict(type="str"), 185 | name=dict( 186 | type="str", 187 | required=True, 188 | ), 189 | region=dict( 190 | type="str", 191 | required=False, 192 | choices=["fr-par", "nl-ams", "pl-waw"], 193 | ), 194 | email_config=dict( 195 | type="dict", 196 | required=False, 197 | ), 198 | webhook_config=dict( 199 | type="dict", 200 | required=False, 201 | ), 202 | organization_id=dict( 203 | type="str", 204 | required=False, 205 | ), 206 | project_id=dict( 207 | type="str", 208 | required=False, 209 | ), 210 | ) 211 | 212 | module = AnsibleModule( 213 | argument_spec=argument_spec, 214 | required_one_of=(["subscriber_id", "name"],), 215 | supports_check_mode=True, 216 | ) 217 | 218 | if not HAS_SCALEWAY_SDK: 219 | module.fail_json(msg=missing_required_lib("scaleway")) 220 | 221 | core(module) 222 | 223 | 224 | if __name__ == "__main__": 225 | main() 226 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_instance_placement_group.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_instance_placement_group 13 | short_description: Manage Scaleway instance's placement_group 14 | description: 15 | - This module can be used to manage Scaleway instance's placement_group. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | placement_group_id: 34 | description: placement_group_id 35 | type: str 36 | required: false 37 | policy_mode: 38 | description: policy_mode 39 | type: str 40 | required: true 41 | choices: 42 | - optional 43 | - enforced 44 | policy_type: 45 | description: policy_type 46 | type: str 47 | required: true 48 | choices: 49 | - max_availability 50 | - low_latency 51 | zone: 52 | description: zone 53 | type: str 54 | required: false 55 | name: 56 | description: name 57 | type: str 58 | required: false 59 | organization: 60 | description: organization 61 | type: str 62 | required: false 63 | project: 64 | description: project 65 | type: str 66 | required: false 67 | tags: 68 | description: tags 69 | type: list 70 | elements: str 71 | required: false 72 | """ 73 | 74 | EXAMPLES = r""" 75 | - name: Create a placement_group 76 | scaleway.scaleway.scaleway_instance_placement_group: 77 | access_key: "{{ scw_access_key }}" 78 | secret_key: "{{ scw_secret_key }}" 79 | policy_mode: "aaaaaa" 80 | policy_type: "aaaaaa" 81 | """ 82 | 83 | RETURN = r""" 84 | --- 85 | placement_group: 86 | description: The placement_group information 87 | returned: when I(state=present) 88 | type: dict 89 | sample: 90 | placement_group: 91 | aaaaaa: bbbbbb 92 | cccccc: dddddd 93 | """ 94 | 95 | from ansible.module_utils.basic import ( 96 | AnsibleModule, 97 | missing_required_lib, 98 | ) 99 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 100 | scaleway_argument_spec, 101 | scaleway_waitable_resource_argument_spec, 102 | scaleway_get_client_from_module, 103 | scaleway_pop_client_params, 104 | scaleway_pop_waitable_resource_params, 105 | ) 106 | 107 | try: 108 | from scaleway import Client 109 | from scaleway.instance.v1 import InstanceV1API 110 | 111 | HAS_SCALEWAY_SDK = True 112 | except ImportError: 113 | HAS_SCALEWAY_SDK = False 114 | 115 | 116 | def create(module: AnsibleModule, client: "Client") -> None: 117 | api = InstanceV1API(client) 118 | 119 | id = module.params.pop("id", None) 120 | if id is not None: 121 | resource = api.get_placement_group(placement_group_id=id) 122 | 123 | if module.check_mode: 124 | module.exit_json(changed=False) 125 | 126 | module.exit_json(changed=False, data=resource) 127 | 128 | if module.check_mode: 129 | module.exit_json(changed=True) 130 | 131 | not_none_params = { 132 | key: value for key, value in module.params.items() if value is not None 133 | } 134 | resource = api.create_placement_group(**not_none_params) 135 | 136 | module.exit_json(changed=True, data=resource.__dict__) 137 | 138 | 139 | def delete(module: AnsibleModule, client: "Client") -> None: 140 | api = InstanceV1API(client) 141 | 142 | placement_group = module.params.pop("placement_group", None) 143 | 144 | if placement_group is not None: 145 | resource = api.get_placement_group( 146 | placement_group_id=placement_group, region=module.params["region"] 147 | ) 148 | else: 149 | module.fail_json(msg="placement_group is required") 150 | 151 | if module.check_mode: 152 | module.exit_json(changed=True) 153 | 154 | api.delete_placement_group( 155 | placement_group_id=resource.placement_group, region=module.params["region"] 156 | ) 157 | 158 | module.exit_json( 159 | changed=True, 160 | msg=f"instance's placement_group {resource.placement_group} deleted", 161 | ) 162 | 163 | 164 | def core(module: AnsibleModule) -> None: 165 | client = scaleway_get_client_from_module(module) 166 | 167 | state = module.params.pop("state") 168 | scaleway_pop_client_params(module) 169 | scaleway_pop_waitable_resource_params(module) 170 | 171 | if state == "present": 172 | create(module, client) 173 | elif state == "absent": 174 | delete(module, client) 175 | 176 | 177 | def main() -> None: 178 | argument_spec = scaleway_argument_spec() 179 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 180 | argument_spec.update( 181 | state=dict(type="str", default="present", choices=["absent", "present"]), 182 | placement_group_id=dict(type="str"), 183 | policy_mode=dict( 184 | type="str", 185 | required=True, 186 | choices=["optional", "enforced"], 187 | ), 188 | policy_type=dict( 189 | type="str", 190 | required=True, 191 | choices=["max_availability", "low_latency"], 192 | ), 193 | zone=dict( 194 | type="str", 195 | required=False, 196 | ), 197 | name=dict( 198 | type="str", 199 | required=False, 200 | ), 201 | organization=dict( 202 | type="str", 203 | required=False, 204 | ), 205 | project=dict( 206 | type="str", 207 | required=False, 208 | ), 209 | tags=dict( 210 | type="list", 211 | required=False, 212 | elements="str", 213 | ), 214 | ) 215 | 216 | module = AnsibleModule( 217 | argument_spec=argument_spec, 218 | required_one_of=(["placement_group_id", "name"],), 219 | supports_check_mode=True, 220 | ) 221 | 222 | if not HAS_SCALEWAY_SDK: 223 | module.fail_json(msg=missing_required_lib("scaleway")) 224 | 225 | core(module) 226 | 227 | 228 | if __name__ == "__main__": 229 | main() 230 | -------------------------------------------------------------------------------- /plugins/modules/scaleway_instance_volume.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # Copyright: (c) 2023, Scaleway 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | from __future__ import absolute_import, division, print_function 7 | 8 | __metaclass__ = type 9 | 10 | DOCUMENTATION = r""" 11 | --- 12 | module: scaleway_instance_volume 13 | short_description: Manage Scaleway instance's volume 14 | description: 15 | - This module can be used to manage Scaleway instance's volume. 16 | version_added: "2.1.0" 17 | author: 18 | - Nathanael Demacon (@quantumsheep) 19 | extends_documentation_fragment: 20 | - scaleway.scaleway.scaleway 21 | - scaleway.scaleway.scaleway_waitable_resource 22 | requirements: 23 | - scaleway >= 0.6.0 24 | options: 25 | state: 26 | description: 27 | - Indicate desired state of the target. 28 | - C(present) will create the resource. 29 | - C(absent) will delete the resource, if it exists. 30 | default: present 31 | choices: ["present", "absent"] 32 | type: str 33 | volume_id: 34 | description: volume_id 35 | type: str 36 | required: false 37 | volume_type: 38 | description: volume_type 39 | type: str 40 | required: true 41 | choices: 42 | - l_ssd 43 | - b_ssd 44 | - unified 45 | zone: 46 | description: zone 47 | type: str 48 | required: false 49 | name: 50 | description: name 51 | type: str 52 | required: false 53 | organization: 54 | description: organization 55 | type: str 56 | required: false 57 | project: 58 | description: project 59 | type: str 60 | required: false 61 | tags: 62 | description: tags 63 | type: list 64 | elements: str 65 | required: false 66 | size: 67 | description: size 68 | type: int 69 | required: false 70 | base_volume: 71 | description: base_volume 72 | type: str 73 | required: false 74 | base_snapshot: 75 | description: base_snapshot 76 | type: str 77 | required: false 78 | """ 79 | 80 | EXAMPLES = r""" 81 | - name: Create a volume 82 | scaleway.scaleway.scaleway_instance_volume: 83 | access_key: "{{ scw_access_key }}" 84 | secret_key: "{{ scw_secret_key }}" 85 | volume_type: "aaaaaa" 86 | """ 87 | 88 | RETURN = r""" 89 | --- 90 | volume: 91 | description: The volume information 92 | returned: when I(state=present) 93 | type: dict 94 | sample: 95 | volume: 96 | aaaaaa: bbbbbb 97 | cccccc: dddddd 98 | """ 99 | 100 | from ansible.module_utils.basic import ( 101 | AnsibleModule, 102 | missing_required_lib, 103 | ) 104 | from ansible_collections.scaleway.scaleway.plugins.module_utils.scaleway import ( 105 | scaleway_argument_spec, 106 | scaleway_waitable_resource_argument_spec, 107 | scaleway_get_client_from_module, 108 | scaleway_pop_client_params, 109 | scaleway_pop_waitable_resource_params, 110 | object_to_dict, 111 | ) 112 | 113 | try: 114 | from scaleway import Client 115 | from scaleway.instance.v1 import InstanceV1API 116 | 117 | HAS_SCALEWAY_SDK = True 118 | except ImportError: 119 | HAS_SCALEWAY_SDK = False 120 | 121 | 122 | def create(module: AnsibleModule, client: "Client") -> None: 123 | api = InstanceV1API(client) 124 | 125 | id = module.params.pop("id", None) 126 | if id is not None: 127 | resource = api.get_volume(volume_id=id) 128 | 129 | if module.check_mode: 130 | module.exit_json(changed=False) 131 | 132 | module.exit_json(changed=False, data=resource) 133 | 134 | if module.check_mode: 135 | module.exit_json(changed=True) 136 | 137 | not_none_params = { 138 | key: value for key, value in module.params.items() if value is not None 139 | } 140 | resource = api.create_volume(**not_none_params) 141 | 142 | module.exit_json(changed=True, data=object_to_dict(resource)) 143 | 144 | 145 | def delete(module: AnsibleModule, client: "Client") -> None: 146 | api = InstanceV1API(client) 147 | 148 | volume = module.params.pop("volume", None) 149 | 150 | if volume is not None: 151 | resource = api.get_volume(volume_id=volume, zone=module.params["zone"]) 152 | else: 153 | module.fail_json(msg="volume is required") 154 | 155 | if module.check_mode: 156 | module.exit_json(changed=True) 157 | 158 | api.delete_volume(volume_id=resource.volume.id, zone=module.params["zone"]) 159 | 160 | module.exit_json( 161 | changed=True, 162 | msg=f"instance's volume {resource.volume} deleted", 163 | ) 164 | 165 | 166 | def core(module: AnsibleModule) -> None: 167 | client = scaleway_get_client_from_module(module) 168 | 169 | state = module.params.pop("state") 170 | scaleway_pop_client_params(module) 171 | scaleway_pop_waitable_resource_params(module) 172 | 173 | if state == "present": 174 | create(module, client) 175 | elif state == "absent": 176 | delete(module, client) 177 | 178 | 179 | def main() -> None: 180 | argument_spec = scaleway_argument_spec() 181 | argument_spec.update(scaleway_waitable_resource_argument_spec()) 182 | argument_spec.update( 183 | state=dict(type="str", default="present", choices=["absent", "present"]), 184 | volume_id=dict(type="str"), 185 | volume_type=dict( 186 | type="str", 187 | required=True, 188 | choices=["l_ssd", "b_ssd", "unified"], 189 | ), 190 | zone=dict( 191 | type="str", 192 | required=False, 193 | ), 194 | name=dict( 195 | type="str", 196 | required=False, 197 | ), 198 | organization=dict( 199 | type="str", 200 | required=False, 201 | ), 202 | project=dict( 203 | type="str", 204 | required=False, 205 | ), 206 | tags=dict( 207 | type="list", 208 | required=False, 209 | elements="str", 210 | ), 211 | size=dict( 212 | type="int", 213 | required=False, 214 | ), 215 | base_volume=dict( 216 | type="str", 217 | required=False, 218 | ), 219 | base_snapshot=dict( 220 | type="str", 221 | required=False, 222 | ), 223 | ) 224 | 225 | module = AnsibleModule( 226 | argument_spec=argument_spec, 227 | required_one_of=(["volume_id", "name"],), 228 | supports_check_mode=True, 229 | ) 230 | 231 | if not HAS_SCALEWAY_SDK: 232 | module.fail_json(msg=missing_required_lib("scaleway")) 233 | 234 | core(module) 235 | 236 | 237 | if __name__ == "__main__": 238 | main() 239 | --------------------------------------------------------------------------------