Compare commits
15 Commits
main
...
feat/dns-z
Author | SHA1 | Date | |
---|---|---|---|
ab996acb36 | |||
2df6309bf1 | |||
83d275f313 | |||
b7e65abd3d | |||
9ed53d92a4 | |||
8bcc020346 | |||
a0e45be691 | |||
29675007db | |||
74c9f8b2f8 | |||
883140deea | |||
194d5ed1f0 | |||
84989cfbee | |||
452a1cd252 | |||
f5fc5bb845 | |||
cd14bbc629 |
67
.gitea/workflows/pull-request-open.yml
Normal file
67
.gitea/workflows/pull-request-open.yml
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
---
|
||||||
|
name: pull-requests-open
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- edited
|
||||||
|
- synchronize
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- develop
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
commit-history-check:
|
||||||
|
name: Check commit compliance
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Install commitizen
|
||||||
|
run: pip3 install commitizen
|
||||||
|
shell: bash
|
||||||
|
working-directory: ${{ gitea.workspace }}
|
||||||
|
|
||||||
|
- name: Verify commit message compliance
|
||||||
|
run: |
|
||||||
|
echo "cz check --rev-range origin/${{ gitea.event.pull_request.base.ref }}.."
|
||||||
|
cz check --rev-range origin/${{ gitea.event.pull_request.base.ref }}..
|
||||||
|
shell: bash
|
||||||
|
working-directory: ${{ gitea.workspace }}
|
||||||
|
|
||||||
|
run-tests:
|
||||||
|
name: Run tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: commit-history-check
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.10"
|
||||||
|
|
||||||
|
- name: Install requirements
|
||||||
|
run: pip3 install -r tests/requirements.txt
|
||||||
|
shell: bash
|
||||||
|
working-directory: ${{ gitea.workspace }}
|
||||||
|
|
||||||
|
- name: Setup testing environment
|
||||||
|
run: ansible-galaxy collection install ${{ gitea.workspace }}
|
||||||
|
shell: bash
|
||||||
|
working-directory: ${{ gitea.workspace }}
|
||||||
|
|
||||||
|
- name: Run ansible unit tests
|
||||||
|
run: ansible-test units --coverage
|
||||||
|
shell: bash
|
||||||
|
working-directory: /root/.ansible/collections/ansible_collections/ednz_cloud/infomaniak
|
||||||
|
|
||||||
|
- name: Print coverage informations
|
||||||
|
run: ansible-test coverage report
|
||||||
|
shell: bash
|
||||||
|
working-directory: /root/.ansible/collections/ansible_collections/ednz_cloud/infomaniak
|
54
.gitea/workflows/release.yml
Normal file
54
.gitea/workflows/release.yml
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
name: release
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
do-release:
|
||||||
|
if: "!startsWith(github.event.head_commit.message, 'bump:')"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Bump version and create changelog with commitizen
|
||||||
|
steps:
|
||||||
|
- name: Get secrets from vault
|
||||||
|
id: import-secrets
|
||||||
|
uses: hashicorp/vault-action@v3
|
||||||
|
with:
|
||||||
|
url: "https://vault.ednz.fr"
|
||||||
|
method: approle
|
||||||
|
roleId: ${{ secrets.VAULT_APPROLE_ID }}
|
||||||
|
secretId: ${{ secrets.VAULT_APPROLE_SECRET_ID }}
|
||||||
|
secrets: |
|
||||||
|
kv/data/applications/gitea/users/actions username | GITEA_ACTIONS_USERNAME ;
|
||||||
|
kv/data/applications/gitea/users/actions token_write | GITEA_ACTIONS_TOKEN ;
|
||||||
|
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
token: ${{ steps.import-secrets.outputs.GITEA_ACTIONS_TOKEN }}
|
||||||
|
|
||||||
|
- name: Install commitizen
|
||||||
|
run: pip3 install commitizen
|
||||||
|
shell: bash
|
||||||
|
working-directory: ${{ gitea.workspace }}
|
||||||
|
|
||||||
|
- name: Configure git credentials
|
||||||
|
uses: oleksiyrudenko/gha-git-credentials@v2
|
||||||
|
with:
|
||||||
|
global: true
|
||||||
|
name: "Gitea-Actions Bot"
|
||||||
|
email: "gitea-actions@ednz.fr"
|
||||||
|
actor: ${{ steps.import-secrets.outputs.GITEA_ACTIONS_USERNAME }}
|
||||||
|
token: ${{ steps.import-secrets.outputs.GITEA_ACTIONS_TOKEN }}
|
||||||
|
|
||||||
|
- name: Do release
|
||||||
|
run: cz -nr 21 bump --yes
|
||||||
|
shell: bash
|
||||||
|
working-directory: ${{ gitea.workspace }}
|
||||||
|
|
||||||
|
- name: Push release
|
||||||
|
run: git push && git push --tags
|
||||||
|
shell: bash
|
||||||
|
working-directory: ${{ gitea.workspace }}
|
19
.gitignore
vendored
19
.gitignore
vendored
@ -1,11 +1,14 @@
|
|||||||
# ignore molecule/testinfra pycache
|
# ignore molecule/testinfra pycache
|
||||||
**/__pycache__
|
**/__pycache__
|
||||||
|
|
||||||
|
# ignore vscode files
|
||||||
.vscode
|
.vscode
|
||||||
roles/ednz_cloud.*
|
|
||||||
vault_config.yml
|
# ignore test output (auto-generated)
|
||||||
consul_config.yml
|
tests/output/**
|
||||||
**/certificates/**
|
|
||||||
**/secrets/credentials.yml
|
# ignore virtual environments
|
||||||
**/secrets/credentials.decrypt.yml
|
.env
|
||||||
**/secrets/vault.yml
|
.venv
|
||||||
**/.ansible-vault
|
env
|
||||||
|
venv
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
namespace: ednz_cloud
|
namespace: ednz_cloud
|
||||||
name: hashistack
|
name: infomaniak
|
||||||
version: 0.7.0
|
version: 0.0.0
|
||||||
readme: README.md
|
readme: README.md
|
||||||
authors:
|
authors:
|
||||||
- Bertrand Lanson <bertrand.lanson@protonmail.com>
|
- Bertrand Lanson <bertrand.lanson@protonmail.com>
|
||||||
@ -11,9 +11,9 @@ license_file: "LICENSE"
|
|||||||
|
|
||||||
# A list of tags you want to associate with the collection for indexing/searching. A tag name has the same character
|
# A list of tags you want to associate with the collection for indexing/searching. A tag name has the same character
|
||||||
# requirements as 'namespace' and 'name'
|
# requirements as 'namespace' and 'name'
|
||||||
tags: ["tools"]
|
tags: ["infomaniak", "cloud"]
|
||||||
dependencies: {}
|
dependencies: {}
|
||||||
repository: https://git.ednz.fr/ansible-collections/hashistack
|
repository: https://git.ednz.fr/ansible-collections/infomaniak
|
||||||
documentation: http://docs.example.com
|
documentation: http://docs.example.com
|
||||||
homepage: http://example.com
|
homepage: http://example.com
|
||||||
issues: http://example.com/issue/tracker
|
issues: http://example.com/issue/tracker
|
||||||
@ -22,7 +22,6 @@ issues: http://example.com/issue/tracker
|
|||||||
# uses 'fnmatch' to match the files or directories. Some directories and files like 'galaxy.yml', '*.pyc', '*.retry',
|
# uses 'fnmatch' to match the files or directories. Some directories and files like 'galaxy.yml', '*.pyc', '*.retry',
|
||||||
# and '.git' are always filtered. Mutually exclusive with 'manifest'
|
# and '.git' are always filtered. Mutually exclusive with 'manifest'
|
||||||
build_ignore:
|
build_ignore:
|
||||||
- assets**
|
|
||||||
- .gitea**
|
- .gitea**
|
||||||
# A dict controlling use of manifest directives used in building the collection artifact. The key 'directives' is a
|
# A dict controlling use of manifest directives used in building the collection artifact. The key 'directives' is a
|
||||||
# list of MANIFEST.in style
|
# list of MANIFEST.in style
|
||||||
|
14
molecule/public_cloud_config_info/converge.yml
Normal file
14
molecule/public_cloud_config_info/converge.yml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
- name: Converge
|
||||||
|
hosts: all
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: "Run module"
|
||||||
|
ednz_cloud.infomaniak.public_cloud_config_info:
|
||||||
|
api_token: "{{ lookup('ansible.builtin.env', 'IK_API_TOKEN') }}"
|
||||||
|
account_id: "{{ lookup('ansible.builtin.env', 'IK_ACCOUNT_ID') }}"
|
||||||
|
register: _result
|
||||||
|
|
||||||
|
- name: "Print result"
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "{{ _result }}"
|
37
molecule/public_cloud_config_info/molecule.yml
Normal file
37
molecule/public_cloud_config_info/molecule.yml
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
dependency:
|
||||||
|
name: galaxy
|
||||||
|
options:
|
||||||
|
requirements-file: ./requirements.yml
|
||||||
|
driver:
|
||||||
|
name: docker
|
||||||
|
platforms:
|
||||||
|
- name: instance
|
||||||
|
image: geerlingguy/docker-${MOLECULE_TEST_OS}-ansible
|
||||||
|
command: ""
|
||||||
|
volumes:
|
||||||
|
- /sys/fs/cgroup:/sys/fs/cgroup
|
||||||
|
cgroupns_mode: host
|
||||||
|
privileged: true
|
||||||
|
pre_build_image: true
|
||||||
|
provisioner:
|
||||||
|
name: ansible
|
||||||
|
config_options:
|
||||||
|
defaults:
|
||||||
|
remote_tmp: /tmp/.ansible
|
||||||
|
verifier:
|
||||||
|
name: ansible
|
||||||
|
scenario:
|
||||||
|
name: public_cloud_config_info
|
||||||
|
test_sequence:
|
||||||
|
- dependency
|
||||||
|
- cleanup
|
||||||
|
- destroy
|
||||||
|
- syntax
|
||||||
|
- create
|
||||||
|
- prepare
|
||||||
|
- converge
|
||||||
|
- idempotence
|
||||||
|
- verify
|
||||||
|
- cleanup
|
||||||
|
- destroy
|
9
molecule/public_cloud_config_info/prepare.yml
Normal file
9
molecule/public_cloud_config_info/prepare.yml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
- name: Converge
|
||||||
|
hosts: all
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: "Install python requirements"
|
||||||
|
ansible.builtin.pip:
|
||||||
|
name: requests
|
||||||
|
executable: pip3
|
4
molecule/public_cloud_config_info/requirements.yml
Normal file
4
molecule/public_cloud_config_info/requirements.yml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
# requirements file for molecule
|
||||||
|
collections:
|
||||||
|
- name: ednz_cloud.infomaniak
|
31
plugins/README.md
Normal file
31
plugins/README.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# Collections Plugins Directory
|
||||||
|
|
||||||
|
This directory can be used to ship various plugins inside an Ansible collection. Each plugin is placed in a folder that
|
||||||
|
is named after the type of plugin it is in. It can also include the `module_utils` and `modules` directory that
|
||||||
|
would contain module utils and modules respectively.
|
||||||
|
|
||||||
|
Here is an example directory of the majority of plugins currently supported by Ansible:
|
||||||
|
|
||||||
|
```
|
||||||
|
└── plugins
|
||||||
|
├── action
|
||||||
|
├── become
|
||||||
|
├── cache
|
||||||
|
├── callback
|
||||||
|
├── cliconf
|
||||||
|
├── connection
|
||||||
|
├── filter
|
||||||
|
├── httpapi
|
||||||
|
├── inventory
|
||||||
|
├── lookup
|
||||||
|
├── module_utils
|
||||||
|
├── modules
|
||||||
|
├── netconf
|
||||||
|
├── shell
|
||||||
|
├── strategy
|
||||||
|
├── terminal
|
||||||
|
├── test
|
||||||
|
└── vars
|
||||||
|
```
|
||||||
|
|
||||||
|
A full list of plugin types can be found at [Working With Plugins](https://docs.ansible.com/ansible-core/2.15/plugins/plugins.html).
|
52
plugins/module_utils/infomaniak_api_client.py
Normal file
52
plugins/module_utils/infomaniak_api_client.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import requests
|
||||||
|
import json
|
||||||
|
|
||||||
|
INFOMANIAK_API_URL = "https://api.infomaniak.com"
|
||||||
|
|
||||||
|
|
||||||
|
class InfomaniakAPIClient:
|
||||||
|
def __init__(self, api_version, api_token):
|
||||||
|
self.base_url = f"{INFOMANIAK_API_URL}/{api_version}"
|
||||||
|
self.headers = {
|
||||||
|
"Authorization": f"Bearer {api_token}",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Accept": "application/json",
|
||||||
|
}
|
||||||
|
|
||||||
|
def _request(self, method, endpoint, data=None, params=None):
|
||||||
|
url = f"{self.base_url}{endpoint}"
|
||||||
|
try:
|
||||||
|
response = requests.request(
|
||||||
|
method=method,
|
||||||
|
url=url,
|
||||||
|
headers=self.headers,
|
||||||
|
json=data,
|
||||||
|
params=params,
|
||||||
|
timeout=10,
|
||||||
|
)
|
||||||
|
response.raise_for_status()
|
||||||
|
try:
|
||||||
|
return response.json()
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
raise Exception(f"Invalid JSON response: {response.text}")
|
||||||
|
except requests.exceptions.HTTPError as http_err:
|
||||||
|
error_content = response.content if response else "No response"
|
||||||
|
raise Exception(
|
||||||
|
f"HTTP error occurred: {http_err}, Response content: {error_content}"
|
||||||
|
)
|
||||||
|
except requests.exceptions.RequestException as req_err:
|
||||||
|
raise Exception(f"Request error occurred: {req_err}")
|
||||||
|
except Exception as err:
|
||||||
|
raise Exception(f"An error occurred: {err}")
|
||||||
|
|
||||||
|
def get(self, endpoint, params=None):
|
||||||
|
return self._request("GET", endpoint, params=params)
|
||||||
|
|
||||||
|
def post(self, endpoint, data=None):
|
||||||
|
return self._request("POST", endpoint, data=data)
|
||||||
|
|
||||||
|
def put(self, endpoint, data=None):
|
||||||
|
return self._request("PUT", endpoint, data=data)
|
||||||
|
|
||||||
|
def delete(self, endpoint):
|
||||||
|
return self._request("DELETE", endpoint)
|
110
plugins/modules/public_cloud_config_info.py
Normal file
110
plugins/modules/public_cloud_config_info.py
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
DOCUMENTATION = r"""
|
||||||
|
---
|
||||||
|
module: ednz_cloud.infomaniak.public_cloud_config_info
|
||||||
|
|
||||||
|
short_description: Retrieves the public cloud configuration from the Infomaniak API.
|
||||||
|
|
||||||
|
version_added: "0.1.0"
|
||||||
|
|
||||||
|
description:
|
||||||
|
- This module queries the Infomaniak API to retrieve the public cloud configuration for a given account.
|
||||||
|
- It uses the provided API token for authentication and the account ID as a query parameter.
|
||||||
|
|
||||||
|
requirements:
|
||||||
|
- C(requests)
|
||||||
|
|
||||||
|
options:
|
||||||
|
api_token:
|
||||||
|
description: The API token used to authenticate with the Infomaniak API.
|
||||||
|
required: true
|
||||||
|
type: str
|
||||||
|
account_id:
|
||||||
|
description: The account ID for which to query the public cloud configuration.
|
||||||
|
required: true
|
||||||
|
type: str
|
||||||
|
|
||||||
|
author:
|
||||||
|
- Bertrand Lanson (@ednxzu)
|
||||||
|
"""
|
||||||
|
|
||||||
|
EXAMPLES = r"""
|
||||||
|
# Example: Retrieve public cloud configuration for account ID 965060
|
||||||
|
- name: Get public cloud configuration
|
||||||
|
public_cloud_config_info:
|
||||||
|
api_token: "your_api_token"
|
||||||
|
account_id: "123456"
|
||||||
|
"""
|
||||||
|
|
||||||
|
RETURN = r"""
|
||||||
|
config:
|
||||||
|
description:
|
||||||
|
- The public cloud configuration for the specified account.
|
||||||
|
type: dict
|
||||||
|
returned: always
|
||||||
|
sample:
|
||||||
|
free_tier: 300
|
||||||
|
free_tier_used: 24.34
|
||||||
|
account_resource_level: 2
|
||||||
|
valid_from: 1707584356
|
||||||
|
valid_to: 1717192799
|
||||||
|
project_count: 2
|
||||||
|
"""
|
||||||
|
|
||||||
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
from ansible_collections.ednz_cloud.infomaniak.plugins.module_utils.infomaniak_api_client import (
|
||||||
|
InfomaniakAPIClient,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_public_cloud_config(client: InfomaniakAPIClient, account_id: str):
|
||||||
|
endpoint = "/public_clouds/config"
|
||||||
|
params = {"account_id": account_id}
|
||||||
|
response = client.get(endpoint, params=params)
|
||||||
|
|
||||||
|
if response.get("result") != "success":
|
||||||
|
raise Exception(f"API request failed with result: {response.get('result')}")
|
||||||
|
|
||||||
|
return response.get("data", {})
|
||||||
|
|
||||||
|
|
||||||
|
def run_module():
|
||||||
|
module_args = dict(
|
||||||
|
api_token=dict(type="str", required=True, no_log=True),
|
||||||
|
account_id=dict(type="str", required=True),
|
||||||
|
)
|
||||||
|
|
||||||
|
result = dict(changed=False, config={})
|
||||||
|
|
||||||
|
module = AnsibleModule(argument_spec=module_args, supports_check_mode=True)
|
||||||
|
|
||||||
|
api_token = module.params["api_token"]
|
||||||
|
account_id = module.params["account_id"]
|
||||||
|
|
||||||
|
if module.check_mode:
|
||||||
|
module.exit_json(
|
||||||
|
changed=False,
|
||||||
|
msg="Check mode: No changes made, would retrieve public cloud config.",
|
||||||
|
)
|
||||||
|
|
||||||
|
client = InfomaniakAPIClient(api_version="1", api_token=api_token)
|
||||||
|
|
||||||
|
try:
|
||||||
|
config_data = get_public_cloud_config(client, account_id)
|
||||||
|
result["config"] = config_data
|
||||||
|
module.exit_json(**result)
|
||||||
|
except Exception as e:
|
||||||
|
module.fail_json(msg=str(e))
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
run_module()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
5
tests/requirements.txt
Normal file
5
tests/requirements.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
ansible==10.3.0
|
||||||
|
requests==2.32.3
|
||||||
|
pytest==8.3.3
|
||||||
|
pytest-xdist==3.6.1
|
||||||
|
coverage==7.3.2
|
194
tests/unit/plugins/modules/test_public_cloud_config_info.py
Normal file
194
tests/unit/plugins/modules/test_public_cloud_config_info.py
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
import unittest
|
||||||
|
import pytest
|
||||||
|
import json
|
||||||
|
from unittest.mock import patch, MagicMock, Mock
|
||||||
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
from ansible.module_utils import basic
|
||||||
|
from ansible.module_utils.common.text.converters import to_bytes
|
||||||
|
from ansible_collections.ednz_cloud.infomaniak.plugins.modules import (
|
||||||
|
public_cloud_config_info,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def set_module_args(args):
|
||||||
|
if "_ansible_remote_tmp" not in args:
|
||||||
|
args["_ansible_remote_tmp"] = "/tmp"
|
||||||
|
if "_ansible_keep_remote_files" not in args:
|
||||||
|
args["_ansible_keep_remote_files"] = False
|
||||||
|
|
||||||
|
args = json.dumps({"ANSIBLE_MODULE_ARGS": args})
|
||||||
|
basic._ANSIBLE_ARGS = to_bytes(args)
|
||||||
|
|
||||||
|
|
||||||
|
class AnsibleExitJson(Exception):
|
||||||
|
def __init__(self, kwargs):
|
||||||
|
self.kwargs = kwargs
|
||||||
|
|
||||||
|
|
||||||
|
def exit_json(*args, **kwargs):
|
||||||
|
if "changed" not in kwargs:
|
||||||
|
kwargs["changed"] = False
|
||||||
|
raise AnsibleExitJson(kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def fail_json(*args, **kwargs):
|
||||||
|
raise SystemExit(json.dumps(kwargs))
|
||||||
|
|
||||||
|
|
||||||
|
class TestPublicCloudConfigInfoModule(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
Unit tests for the public_cloud_config_info Ansible module.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@patch(
|
||||||
|
"ansible_collections.ednz_cloud.infomaniak.plugins.modules.public_cloud_config_info.AnsibleModule"
|
||||||
|
)
|
||||||
|
@patch(
|
||||||
|
"ansible_collections.ednz_cloud.infomaniak.plugins.modules.public_cloud_config_info.InfomaniakAPIClient"
|
||||||
|
)
|
||||||
|
def test_successful_retrieval(self, mock_client_class, mock_ansible_module):
|
||||||
|
"""
|
||||||
|
Test a successful retrieval of public cloud configuration.
|
||||||
|
"""
|
||||||
|
api_response_data = {
|
||||||
|
"result": "success",
|
||||||
|
"data": {
|
||||||
|
"free_tier": 300,
|
||||||
|
"free_tier_used": 24.34,
|
||||||
|
"account_resource_level": 2,
|
||||||
|
"valid_from": 1707584356,
|
||||||
|
"valid_to": 1717192799,
|
||||||
|
"project_count": 2,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
mock_client_instance = MagicMock()
|
||||||
|
mock_client_instance.get.return_value = api_response_data
|
||||||
|
mock_client_class.return_value = mock_client_instance
|
||||||
|
|
||||||
|
mock_module_instance = MagicMock()
|
||||||
|
mock_module_instance.params = {
|
||||||
|
"api_token": "mock_api_token",
|
||||||
|
"account_id": "mock_account_id",
|
||||||
|
}
|
||||||
|
mock_module_instance.check_mode = False
|
||||||
|
mock_ansible_module.return_value = mock_module_instance
|
||||||
|
|
||||||
|
mock_module_instance.exit_json = MagicMock()
|
||||||
|
|
||||||
|
public_cloud_config_info.run_module()
|
||||||
|
|
||||||
|
mock_client_class.assert_called_with(
|
||||||
|
api_version="1", api_token="mock_api_token"
|
||||||
|
)
|
||||||
|
|
||||||
|
mock_client_instance.get.assert_called_once_with(
|
||||||
|
"/public_clouds/config", params={"account_id": "mock_account_id"}
|
||||||
|
)
|
||||||
|
|
||||||
|
mock_module_instance.exit_json.assert_called_once_with(
|
||||||
|
changed=False, config=api_response_data["data"]
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_missing_required_params(self):
|
||||||
|
"""
|
||||||
|
Test behavior when required parameters are missing.
|
||||||
|
"""
|
||||||
|
set_module_args(
|
||||||
|
{
|
||||||
|
"api_token": "mock_api_token",
|
||||||
|
# 'account_id' is missing
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch.object(AnsibleModule, "fail_json", side_effect=fail_json):
|
||||||
|
with pytest.raises(SystemExit) as e:
|
||||||
|
public_cloud_config_info.main()
|
||||||
|
|
||||||
|
captured_output = json.loads(e.value.args[0])
|
||||||
|
|
||||||
|
assert "msg" in captured_output
|
||||||
|
assert "missing required arguments: account_id" in captured_output["msg"]
|
||||||
|
|
||||||
|
def test_check_mode(self):
|
||||||
|
"""
|
||||||
|
Test the behavior in check mode, where no changes should be made.
|
||||||
|
"""
|
||||||
|
set_module_args(
|
||||||
|
{
|
||||||
|
"api_token": "mock_api_token",
|
||||||
|
"account_id": "mock_account_id",
|
||||||
|
"_ansible_check_mode": True,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch.object(
|
||||||
|
AnsibleModule, "exit_json", side_effect=exit_json
|
||||||
|
) as mock_exit_json:
|
||||||
|
with pytest.raises(AnsibleExitJson) as e:
|
||||||
|
public_cloud_config_info.main()
|
||||||
|
|
||||||
|
mock_exit_json.assert_called_once_with(
|
||||||
|
changed=False,
|
||||||
|
msg="Check mode: No changes made, would retrieve public cloud config.",
|
||||||
|
)
|
||||||
|
|
||||||
|
@patch(
|
||||||
|
"ansible_collections.ednz_cloud.infomaniak.plugins.modules.public_cloud_config_info.InfomaniakAPIClient"
|
||||||
|
)
|
||||||
|
def test_network_timeout(self, mock_client_class):
|
||||||
|
"""
|
||||||
|
Test behavior when a network timeout occurs.
|
||||||
|
"""
|
||||||
|
# Simulate a network timeout error
|
||||||
|
mock_client_instance = MagicMock()
|
||||||
|
mock_client_instance.get.side_effect = Exception("Request timeout")
|
||||||
|
mock_client_class.return_value = mock_client_instance
|
||||||
|
|
||||||
|
set_module_args(
|
||||||
|
{
|
||||||
|
"api_token": "mock_api_token",
|
||||||
|
"account_id": "mock_account_id",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch.object(
|
||||||
|
AnsibleModule, "fail_json", side_effect=fail_json
|
||||||
|
) as mock_fail_json:
|
||||||
|
with pytest.raises(SystemExit) as e:
|
||||||
|
public_cloud_config_info.main()
|
||||||
|
|
||||||
|
captured_output = json.loads(e.value.args[0])
|
||||||
|
assert "msg" in captured_output
|
||||||
|
assert captured_output["msg"] == "Request timeout"
|
||||||
|
mock_fail_json.assert_called_once()
|
||||||
|
|
||||||
|
@patch(
|
||||||
|
"ansible_collections.ednz_cloud.infomaniak.plugins.modules.public_cloud_config_info.InfomaniakAPIClient"
|
||||||
|
)
|
||||||
|
def test_invalid_json_response(self, mock_client_class):
|
||||||
|
"""
|
||||||
|
Test behavior when the API returns an invalid JSON response.
|
||||||
|
"""
|
||||||
|
mock_client_instance = MagicMock()
|
||||||
|
mock_client_instance.get.side_effect = Exception("Invalid JSON response")
|
||||||
|
mock_client_class.return_value = mock_client_instance
|
||||||
|
|
||||||
|
# Set module args with the required parameters
|
||||||
|
set_module_args(
|
||||||
|
{
|
||||||
|
"api_token": "mock_api_token",
|
||||||
|
"account_id": "mock_account_id",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch.object(
|
||||||
|
AnsibleModule, "fail_json", side_effect=fail_json
|
||||||
|
) as mock_fail_json:
|
||||||
|
with pytest.raises(SystemExit) as e:
|
||||||
|
public_cloud_config_info.main()
|
||||||
|
|
||||||
|
captured_output = json.loads(e.value.args[0])
|
||||||
|
assert "msg" in captured_output
|
||||||
|
assert captured_output["msg"] == "Invalid JSON response"
|
||||||
|
mock_fail_json.assert_called_once()
|
Loading…
Reference in New Issue
Block a user