feat/dns-zone-info #1
53
.gitea/workflows/pull-request-open.yml
Normal file
53
.gitea/workflows/pull-request-open.yml
Normal file
@ -0,0 +1,53 @@
|
||||
---
|
||||
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
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install requirements
|
||||
run: pip3 install -r tests/requirements.txt
|
||||
shell: bash
|
||||
working-directory: ${{ gitea.workspace }}
|
||||
|
||||
- name: Run ansible unit tests
|
||||
uses: ansible-community/ansible-test-gh-action@release/v1
|
||||
with:
|
||||
ansible-core-version: v2.17.4
|
||||
testing-type: units
|
||||
collection-src-directory: ${{ gitea.workspace }}
|
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
|
||||
**/__pycache__
|
||||
|
||||
# ignore vscode files
|
||||
.vscode
|
||||
roles/ednz_cloud.*
|
||||
vault_config.yml
|
||||
consul_config.yml
|
||||
**/certificates/**
|
||||
**/secrets/credentials.yml
|
||||
**/secrets/credentials.decrypt.yml
|
||||
**/secrets/vault.yml
|
||||
**/.ansible-vault
|
||||
|
||||
# ignore test output (auto-generated)
|
||||
tests/output/**
|
||||
|
||||
# ignore virtual environments
|
||||
.env
|
||||
.venv
|
||||
env
|
||||
venv
|
||||
|
@ -79,7 +79,7 @@ def run_module():
|
||||
account_id=dict(type="str", required=True),
|
||||
)
|
||||
|
||||
result = dict(changed=False, public_cloud_config={})
|
||||
result = dict(changed=False, config={})
|
||||
|
||||
module = AnsibleModule(argument_spec=module_args, supports_check_mode=True)
|
||||
|
||||
|
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
|
292
tests/unit/plugins/modules/test_public_cloud_config_info.py
Normal file
292
tests/unit/plugins/modules/test_public_cloud_config_info.py
Normal file
@ -0,0 +1,292 @@
|
||||
import unittest
|
||||
from unittest.mock import patch, MagicMock
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.ednz_cloud.infomaniak.plugins.modules import (
|
||||
public_cloud_config_info,
|
||||
)
|
||||
|
||||
|
||||
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.
|
||||
"""
|
||||
# Mock API response data
|
||||
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 the InfomaniakAPIClient instance
|
||||
mock_client_instance = MagicMock()
|
||||
mock_client_instance.get.return_value = api_response_data
|
||||
mock_client_class.return_value = mock_client_instance
|
||||
|
||||
# Mock AnsibleModule parameters
|
||||
mock_module_instance = MagicMock()
|
||||
mock_module_instance.params = {
|
||||
"api_token": "mock_api_token",
|
||||
"account_id": "mock_account_id",
|
||||
}
|
||||
mock_module_instance.check_mode = False # Simulate non-check mode
|
||||
mock_ansible_module.return_value = mock_module_instance
|
||||
|
||||
# Mock exit_json to prevent actual exit
|
||||
mock_module_instance.exit_json = MagicMock()
|
||||
|
||||
# Execute the run_module function
|
||||
public_cloud_config_info.run_module()
|
||||
|
||||
# Assert that the InfomaniakAPIClient was initialized with the correct token
|
||||
mock_client_class.assert_called_with(
|
||||
api_version="1", api_token="mock_api_token"
|
||||
)
|
||||
|
||||
# Assert that the correct API call was made
|
||||
mock_client_instance.get.assert_called_once_with(
|
||||
"/public_clouds/config", params={"account_id": "mock_account_id"}
|
||||
)
|
||||
|
||||
# Assert exit_json is called once with the expected data
|
||||
mock_module_instance.exit_json.assert_called_once_with(
|
||||
changed=False, config=api_response_data["data"]
|
||||
)
|
||||
|
||||
@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_api_failure(self, mock_client_class, mock_ansible_module):
|
||||
"""
|
||||
Test failure scenario where API returns an error result.
|
||||
"""
|
||||
|
||||
# Mock API failure response
|
||||
mock_client_instance = MagicMock()
|
||||
mock_client_instance.get.side_effect = Exception(
|
||||
"API request failed with result: error"
|
||||
)
|
||||
mock_client_class.return_value = mock_client_instance
|
||||
|
||||
# Mock AnsibleModule parameters
|
||||
mock_module_instance = MagicMock()
|
||||
mock_module_instance.params = {
|
||||
"api_token": "mock_api_token",
|
||||
"account_id": "invalid_account_id",
|
||||
}
|
||||
mock_module_instance.check_mode = False # Simulate non-check mode
|
||||
mock_ansible_module.return_value = mock_module_instance
|
||||
|
||||
# Mock fail_json to prevent actual exit
|
||||
mock_module_instance.fail_json = MagicMock()
|
||||
|
||||
# Execute the run_module function
|
||||
public_cloud_config_info.run_module()
|
||||
|
||||
# Assert fail_json was called with the expected error message
|
||||
mock_module_instance.fail_json.assert_called_once_with(
|
||||
msg="API request failed with result: error"
|
||||
)
|
||||
|
||||
@patch(
|
||||
"ansible_collections.ednz_cloud.infomaniak.plugins.modules.public_cloud_config_info.AnsibleModule"
|
||||
)
|
||||
def test_missing_required_params(self, mock_ansible_module):
|
||||
"""
|
||||
Test behavior when required parameters are missing.
|
||||
"""
|
||||
# Mock the AnsibleModule instance
|
||||
mock_module_instance = MagicMock()
|
||||
|
||||
# Simulate missing 'api_token' in the parameters
|
||||
mock_module_instance.params = {
|
||||
"account_id": "mock_account_id", # Missing api_token
|
||||
}
|
||||
|
||||
# Simulate Ansible behavior: fail_json should be called when 'api_token' is missing
|
||||
mock_ansible_module.return_value = mock_module_instance
|
||||
|
||||
# Execute the run_module function and expect KeyError
|
||||
with self.assertRaises(KeyError):
|
||||
public_cloud_config_info.run_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_empty_api_response(self, mock_client_class, mock_ansible_module):
|
||||
"""
|
||||
Test behavior when the API returns an empty response.
|
||||
"""
|
||||
# Mock API response data
|
||||
api_response_data = {"result": "success", "data": {}} # Empty data
|
||||
|
||||
# Mock the InfomaniakAPIClient instance
|
||||
mock_client_instance = MagicMock()
|
||||
mock_client_instance.get.return_value = api_response_data
|
||||
mock_client_class.return_value = mock_client_instance
|
||||
|
||||
# Mock AnsibleModule parameters
|
||||
mock_module_instance = MagicMock()
|
||||
mock_module_instance.params = {
|
||||
"api_token": "mock_api_token",
|
||||
"account_id": "mock_account_id",
|
||||
}
|
||||
mock_module_instance.check_mode = False # Simulate non-check mode
|
||||
mock_ansible_module.return_value = mock_module_instance
|
||||
|
||||
# Execute the run_module function
|
||||
public_cloud_config_info.run_module()
|
||||
|
||||
# Assert exit_json is called once with empty config data
|
||||
mock_module_instance.exit_json.assert_called_once_with(changed=False, config={})
|
||||
|
||||
@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_unexpected_api_response_format(
|
||||
self, mock_client_class, mock_ansible_module
|
||||
):
|
||||
"""
|
||||
Test behavior when the API response format is unexpected.
|
||||
"""
|
||||
# Mock an unexpected API response (missing 'result')
|
||||
api_response_data = {
|
||||
"data": {
|
||||
"free_tier": 300,
|
||||
}
|
||||
}
|
||||
|
||||
# Mock the InfomaniakAPIClient instance
|
||||
mock_client_instance = MagicMock()
|
||||
mock_client_instance.get.return_value = api_response_data
|
||||
mock_client_class.return_value = mock_client_instance
|
||||
|
||||
# Mock AnsibleModule parameters
|
||||
mock_module_instance = MagicMock()
|
||||
mock_module_instance.params = {
|
||||
"api_token": "mock_api_token",
|
||||
"account_id": "mock_account_id",
|
||||
}
|
||||
mock_ansible_module.return_value = mock_module_instance
|
||||
|
||||
# Execute the run_module function
|
||||
public_cloud_config_info.run_module()
|
||||
|
||||
# Assert fail_json is called with an appropriate error
|
||||
mock_module_instance.fail_json.assert_called_once_with(
|
||||
msg="API request failed with result: None"
|
||||
)
|
||||
|
||||
@patch(
|
||||
"ansible_collections.ednz_cloud.infomaniak.plugins.modules.public_cloud_config_info.AnsibleModule"
|
||||
)
|
||||
def test_check_mode(self, mock_ansible_module):
|
||||
"""
|
||||
Test behavior when check_mode is enabled.
|
||||
"""
|
||||
# Mock AnsibleModule parameters
|
||||
mock_module_instance = MagicMock()
|
||||
mock_module_instance.params = {
|
||||
"api_token": "mock_api_token",
|
||||
"account_id": "mock_account_id",
|
||||
}
|
||||
mock_module_instance.check_mode = True # Simulate check mode
|
||||
mock_ansible_module.return_value = mock_module_instance
|
||||
|
||||
# Execute the run_module function
|
||||
public_cloud_config_info.run_module()
|
||||
|
||||
# Assert exit_json is called with the check_mode message
|
||||
mock_module_instance.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.AnsibleModule"
|
||||
)
|
||||
@patch(
|
||||
"ansible_collections.ednz_cloud.infomaniak.plugins.modules.public_cloud_config_info.InfomaniakAPIClient"
|
||||
)
|
||||
def test_network_timeout(self, mock_client_class, mock_ansible_module):
|
||||
"""
|
||||
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
|
||||
|
||||
# Mock AnsibleModule parameters
|
||||
mock_module_instance = MagicMock()
|
||||
mock_module_instance.params = {
|
||||
"api_token": "mock_api_token",
|
||||
"account_id": "mock_account_id",
|
||||
}
|
||||
mock_ansible_module.return_value = mock_module_instance
|
||||
|
||||
# Execute the run_module function
|
||||
public_cloud_config_info.run_module()
|
||||
|
||||
# Assert fail_json is called with the timeout error message
|
||||
mock_module_instance.fail_json.assert_called_once_with(msg="Request timeout")
|
||||
|
||||
@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_invalid_json_response(self, mock_client_class, mock_ansible_module):
|
||||
"""
|
||||
Test behavior when the API returns an invalid JSON response.
|
||||
"""
|
||||
# Mock the InfomaniakAPIClient instance to raise a JSONDecodeError
|
||||
mock_client_instance = MagicMock()
|
||||
mock_client_instance.get.side_effect = Exception("Invalid JSON response")
|
||||
mock_client_class.return_value = mock_client_instance
|
||||
|
||||
# Mock AnsibleModule parameters
|
||||
mock_module_instance = MagicMock()
|
||||
mock_module_instance.params = {
|
||||
"api_token": "mock_api_token",
|
||||
"account_id": "mock_account_id",
|
||||
}
|
||||
mock_ansible_module.return_value = mock_module_instance
|
||||
|
||||
# Execute the run_module function
|
||||
public_cloud_config_info.run_module()
|
||||
|
||||
# Assert fail_json is called with the appropriate error message
|
||||
mock_module_instance.fail_json.assert_called_once_with(
|
||||
msg="Invalid JSON response"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
Loading…
Reference in New Issue
Block a user