Skip to content

Commit e6ea847

Browse files
committed
test: add sanity check on collection and fix sanity issues
1 parent 3722a13 commit e6ea847

File tree

11 files changed

+156
-55
lines changed

11 files changed

+156
-55
lines changed

.github/workflows/test.yml

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,39 @@ jobs:
1010
integration-test:
1111
environment: test
1212
runs-on: ubuntu-latest
13+
defaults:
14+
run:
15+
working-directory: ansible/ansible_collections/devolutions/dvls
1316

1417
steps:
1518
- name: Checkout code
1619
uses: actions/checkout@v4
20+
with:
21+
path: ansible/ansible_collections/devolutions/dvls
1722

1823
- name: Set up Python
1924
uses: actions/setup-python@v4
2025
with:
21-
python-version: 3.x
26+
python-version: 3.13
2227

23-
- name: Install Python dependencies
28+
- name: Create virtual environment and install dependencies
2429
run: |
30+
echo "Creating python virtual environment"
2531
python3 -m pip install --upgrade pip
26-
python3 -m pip install -r requirements.txt
27-
python3 -m pip list
32+
python3 -m venv test
33+
echo "Activating python virtual environment"
34+
source test/bin/activate
35+
if [ -f requirements.txt ]; then
36+
echo "Installing python requirements"
37+
python3 -m pip install --upgrade pip
38+
python3 -m pip install -r requirements.txt
39+
python3 -m pip list
40+
fi
41+
42+
- name: Test collection sanity
43+
run: ansible-test sanity
2844

29-
- name: Build
45+
- name: Build collection
3046
id: build
3147
run: |
3248
OUTPUT=$(ansible-galaxy collection build)
@@ -37,11 +53,30 @@ jobs:
3753
3854
- name: Install collection
3955
run: ansible-galaxy collection install ${{ steps.build.outputs.collection_path }} --force
40-
working-directory: tests/integration
56+
working-directory: ansible/ansible_collections/devolutions/dvls/tests/integration
57+
58+
- name: Test collection documentation
59+
run: |
60+
# Generate the list of modules dynamically
61+
ansible_modules=($(ansible-doc -l devolutions.dvls | awk '{print $1}'))
62+
63+
# Check if any modules were found
64+
if [ ${#ansible_modules[@]} -eq 0 ]; then
65+
echo "Error: No modules found for devolutions.dvls."
66+
exit 1
67+
fi
68+
echo "Modules: ${ansible_modules[@]}"
69+
70+
# Loop through each module and run ansible-doc
71+
for ansible_module in "${ansible_modules[@]}"; do
72+
echo "Running ansible-doc for module: $ansible_module"
73+
ansible-doc -t module "$ansible_module"
74+
echo "----------------------------------------------------"
75+
done
4176
4277
- name: Run get-vaults
4378
run: ansible-playbook test_manage_server.yml
44-
working-directory: tests/integration
79+
working-directory: ansible/ansible_collections/devolutions/dvls/tests/integration
4580
env:
4681
DVLS_APP_KEY: ${{ secrets.DVLS_APP_KEY }}
4782
DVLS_APP_SECRET: ${{ secrets.DVLS_APP_SECRET }}
@@ -50,7 +85,7 @@ jobs:
5085

5186
- name: Run get-secrets
5287
run: ansible-playbook test_manage_secrets.yml
53-
working-directory: tests/integration
88+
working-directory: ansible/ansible_collections/devolutions/dvls/tests/integration
5489
env:
5590
DVLS_APP_KEY: ${{ secrets.DVLS_APP_KEY }}
5691
DVLS_APP_SECRET: ${{ secrets.DVLS_APP_SECRET }}

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
.lock
44
.ansible
55

6+
# asnible-test
7+
output
8+
69
# vscode..
710
.vscode
811

README.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -129,16 +129,16 @@ Example response
129129

130130
## Secrets definition
131131

132-
To access a particular field within a secret, you can use the format ```{{ secrets['name-or-id'].value }}```. Heres a breakdown of the available categories and their fields:
133-
134-
| **Category** | **Fields** |
135-
|---------------------------|---------------------------------------------------------------------------|
136-
| Username and password | `domain`, `password`, `username` |
137-
| Connection string | `connectionString` |
138-
| Secret | `password` |
139-
| API key | `apiId`, `apiKey`, `tenantId` |
132+
To access a particular field within a secret, you can use the format ```{{ secrets['name-or-id'].value }}```. Here's a breakdown of the available categories and their fields:
133+
134+
| **Category** | **Fields** |
135+
|---------------------------|---------------------------------------------------------------------------------------------------------------------------|
136+
| Username and password | `domain`, `password`, `username` |
137+
| Connection string | `connectionString` |
138+
| Secret | `password` |
139+
| API key | `apiId`, `apiKey`, `tenantId` |
140140
| SSH key | `domain`, `password`, `privateKeyData`, `privateKeyOverridePassword`, `privateKeyPassPhrase`, `publicKeyData`, `username` |
141-
| Azure service principal | `clientId`, `clientSecret`, `tenantId` |
141+
| Azure service principal | `clientId`, `clientSecret`, `tenantId` |
142142

143143

144144
### Example using secret value

meta/runtime.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
requires_ansible: '>=2.9.10'
2+
requires_ansible: '~=2.18'

plugins/module_utils/auth.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
1-
import requests
21
import json
2+
import traceback
3+
4+
try:
5+
import requests
6+
except ImportError:
7+
HAS_REQUESTS_LIBRARY = False
8+
REQUESTS_LIBRARY_IMPORT_ERROR = traceback.format_exc()
9+
else:
10+
HAS_REQUESTS_LIBRARY_LIBRARY = True
11+
REQUESTS_LIBRARY_IMPORT_ERROR = None
312

413

514
def login(server_base_url, app_key, app_secret):

plugins/module_utils/server.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
1-
import requests
1+
import traceback
2+
3+
try:
4+
import requests
5+
except ImportError:
6+
HAS_REQUESTS_LIBRARY = False
7+
REQUESTS_LIBRARY_IMPORT_ERROR = traceback.format_exc()
8+
else:
9+
HAS_REQUESTS_LIBRARY_LIBRARY = True
10+
REQUESTS_LIBRARY_IMPORT_ERROR = None
211

312

413
def public_instance_information(server_base_url, token):

plugins/module_utils/vaults.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
1-
import requests
1+
import traceback
2+
3+
try:
4+
import requests
5+
except ImportError:
6+
HAS_REQUESTS_LIBRARY = False
7+
REQUESTS_LIBRARY_IMPORT_ERROR = traceback.format_exc()
8+
else:
9+
HAS_REQUESTS_LIBRARY_LIBRARY = True
10+
REQUESTS_LIBRARY_IMPORT_ERROR = None
211

312

413
def get_vaults(server_base_url, token):

plugins/modules/create_secret.py

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
short_description: create or update a credential to DVLS
88
99
description:
10-
- This module logs into the DVLS (Devolutions Server) service, checks if a entry inside a given path already exists and updates or creates a Credential by name.
11-
- The module requires DVLS application credentials, a server base URL and the data needed to create a secret.
10+
- Logs into the DVLS (Devolutions Server) service, checks if an entry exists at a given path, and updates or creates a Credential by name.
11+
- Requires DVLS application credentials, a server base URL and the data needed to create a secret.
1212
1313
options:
1414
server_base_url:
@@ -30,8 +30,7 @@
3030
secret:
3131
description: the credential object, containing username and password.
3232
required: true
33-
type: list
34-
elements: dict
33+
type: dict
3534
suboptions:
3635
secret_name:
3736
description: the entry name/username.
@@ -49,7 +48,7 @@
4948
description: the type of secret that will get created.
5049
required: false
5150
type: str
52-
default: Credentials
51+
default: Credential
5352
secret_subtype:
5453
description: the secret subtype.
5554
required: false
@@ -65,7 +64,7 @@
6564
"""
6665

6766
EXAMPLES = r"""
68-
- name: Upload Credentials to DVLS
67+
- name: Upload Credential to DVLS
6968
devolutions.dvls.create_secret:
7069
server_base_url: "https://example.yourcompany.com"
7170
app_key: "{{ lookup('env', 'DVLS_APP_KEY') }}"
@@ -82,40 +81,62 @@
8281
description: returns the ID of the created/updated entry.
8382
type: dict
8483
returned: changed
84+
8585
"""
8686

87-
from ansible.module_utils.basic import AnsibleModule
87+
import traceback
88+
89+
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
8890
from ansible_collections.devolutions.dvls.plugins.module_utils.auth import login, logout
8991
from ansible_collections.devolutions.dvls.plugins.module_utils.vaults import (
9092
get_vault_entries,
9193
find_entry_by_name,
9294
)
93-
import requests
95+
96+
try:
97+
import requests
98+
except ImportError:
99+
HAS_REQUESTS_LIBRARY = False
100+
REQUESTS_LIBRARY_IMPORT_ERROR = traceback.format_exc()
101+
else:
102+
HAS_REQUESTS_LIBRARY = True
103+
REQUESTS_LIBRARY_IMPORT_ERROR = None
94104

95105

96106
def run_module():
97-
module_args = dict(
107+
argument_spec = dict(
98108
server_base_url=dict(type="str", required=True),
99-
app_key=dict(type="str", required=True),
100-
app_secret=dict(type="str", required=True),
109+
app_key=dict(type="str", required=True, no_log=True),
110+
app_secret=dict(type="str", required=True, no_log=True),
101111
vault_id=dict(type="str", required=True),
102112
secret=dict(
103113
type="dict",
104114
options=dict(
105-
secret_name=dict(type="str", required=True),
106-
value=dict(type="str", required=True),
107-
secret_path=dict(type="str", required=False),
108-
secret_type=dict(type="str", required=False, default="Credential"),
109-
secret_subtype=dict(type="str", required=False, default="Default"),
110-
secret_description=dict(type="str", required=False),
115+
secret_name=dict(type="str", required=True, no_log=False),
116+
value=dict(type="str", required=True, no_log=True),
117+
secret_path=dict(type="str", required=False, no_log=False),
118+
secret_type=dict(
119+
type="str", required=False, default="Credential", no_log=False
120+
),
121+
secret_subtype=dict(
122+
type="str", required=False, default="Default", no_log=False
123+
),
124+
secret_description=dict(type="str", required=False, no_log=False),
111125
),
112126
required=True,
127+
no_log=False,
113128
),
114129
)
115130

116131
result = dict()
117132

118-
module = AnsibleModule(argument_spec=module_args, supports_check_mode=True)
133+
module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
134+
135+
if not HAS_REQUESTS_LIBRARY:
136+
module.fail_json(
137+
msg=missing_required_lib("requests"),
138+
exception=REQUESTS_LIBRARY_IMPORT_ERROR,
139+
)
119140

120141
if module.check_mode:
121142
module.exit_json(**result)

plugins/modules/fetch_secrets.py

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
short_description: Fetch secrets from DVLS
88
99
description:
10-
- This module logs into the DVLS (Devolutions Server) service, retrieves specified secrets from a specified vault by name or ID.
11-
- The module requires DVLS application credentials, a server base URL, and either a secret name or ID.
10+
- Logs into the DVLS (Devolutions Server) service, retrieves specified secrets from a specified vault by name or ID.
11+
- Requires DVLS application credentials, a server base URL, and either a secret name or ID.
1212
1313
options:
1414
server_base_url:
@@ -29,7 +29,6 @@
2929
type: str
3030
secrets:
3131
description: A list of secrets to fetch. Each secret can be specified by name or ID.
32-
required: true
3332
type: list
3433
elements: dict
3534
suboptions:
@@ -41,6 +40,18 @@
4140
description: The ID of the secret to fetch.
4241
required: false
4342
type: str
43+
secret_path:
44+
description: The path of the secret to fetch.
45+
required: false
46+
type: str
47+
secret_type:
48+
description: The type of the secret to fetch.
49+
required: false
50+
type: str
51+
secret_tag:
52+
description: The tag of the secret to fetch.
53+
required: false
54+
type: str
4455
4556
author:
4657
- Danny Bédard (@DannyBedard)
@@ -85,20 +96,21 @@
8596
def run_module():
8697
module_args = dict(
8798
server_base_url=dict(type="str", required=True),
88-
app_key=dict(type="str", required=True),
89-
app_secret=dict(type="str", required=True),
99+
app_key=dict(type="str", required=True, no_log=True),
100+
app_secret=dict(type="str", required=True, no_log=True),
90101
vault_id=dict(type="str", required=True),
91102
secrets=dict(
92103
type="list",
93104
elements="dict",
94105
options=dict(
95-
secret_name=dict(type="str", required=False),
96-
secret_id=dict(type="str", required=False),
97-
secret_path=dict(type="str", required=False),
98-
secret_type=dict(type="str", required=False),
99-
secret_tag=dict(type="str", required=False),
106+
secret_name=dict(type="str", required=False, no_log=False),
107+
secret_id=dict(type="str", required=False, no_log=False),
108+
secret_path=dict(type="str", required=False, no_log=False),
109+
secret_type=dict(type="str", required=False, no_log=False),
110+
secret_tag=dict(type="str", required=False, no_log=False),
100111
),
101112
required=False,
113+
no_log=False,
102114
),
103115
)
104116

plugins/modules/fetch_server.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
short_description: Fetch server from DVLS
88
99
description:
10-
- This module logs into the DVLS (Devolutions Server) service, retrieves server information and vaults list.
11-
- The module requires DVLS application credentials and a server base URL.
10+
- Logs into the DVLS (Devolutions Server) service, retrieves server information and vaults list.
11+
- Requires DVLS application credentials and a server base URL.
1212
1313
options:
1414
server_base_url:
@@ -30,11 +30,11 @@
3030

3131
EXAMPLES = r"""
3232
- name: Fetch dvls server information
33-
server:
33+
devolutions.dvls.fetch_server:
3434
server_base_url: "https://example.yourcompany.com"
3535
app_key: "{{ lookup('env', 'DVLS_APP_KEY') }}"
3636
app_secret: "{{ lookup('env', 'DVLS_APP_SECRET') }}"
37-
register: server
37+
register: server
3838
"""
3939

4040
RETURN = r"""
@@ -56,8 +56,8 @@
5656
def run_module():
5757
module_args = dict(
5858
server_base_url=dict(type="str", required=True),
59-
app_key=dict(type="str", required=True),
60-
app_secret=dict(type="str", required=True),
59+
app_key=dict(type="str", required=True, no_log=True),
60+
app_secret=dict(type="str", required=True, no_log=True),
6161
)
6262

6363
result = dict()

0 commit comments

Comments
 (0)