Skip to content

Commit 15d6db6

Browse files
Merge branch 'main' into shivashankar-vaddepally-patch-1
2 parents 9d5127d + cbd6a7b commit 15d6db6

22 files changed

Lines changed: 1375 additions & 108 deletions

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
.vscode/
22

3-
tools/
43
issues/
54

65
plugins/module_utils/test.ipynb

CHANGELOG.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [2.10.1] - 2025-09-16
11+
12+
# Fixed
13+
14+
- Resolved error while importing new SSL certificate with duplicate primary key error
15+
16+
## [2.10.0] - 2025-08-22
17+
18+
### Added
19+
20+
- Added migration tool to convert `citrix.adc` module playbooks to `netscaler.adc`.
21+
22+
### Fixed
23+
24+
- Added option to skip non-updatable resources or fail explicitly
25+
- Removal of basic authentication from Netscaler ADC Ansible collection
26+
- Fixed idempotency issue in rename operations
27+
- Fixed GET request URL for global bindings to include type query parameter
28+
1029
## [2.9.2] - 2025-06-25
1130

1231
### Fixed
@@ -177,7 +196,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
177196
### Added
178197

179198
- Initial Release
180-
[unreleased]: https://github.com/netscaler/ansible-collection-netscaleradc/compare/2.9.2...HEAD
199+
200+
[unreleased]: https://github.com/netscaler/ansible-collection-netscaleradc/compare/2.10.1...HEAD
201+
[2.10.1]: https://github.com/netscaler/ansible-collection-netscaleradc/compare/2.10.0...2.10.1
202+
[2.10.0]: https://github.com/netscaler/ansible-collection-netscaleradc/compare/2.9.2...2.10.0
181203
[2.9.2]: https://github.com/netscaler/ansible-collection-netscaleradc/compare/2.9.1...2.9.2
182204
[2.9.1]: https://github.com/netscaler/ansible-collection-netscaleradc/compare/2.9.0...2.9.1
183205
[2.9.0]: https://github.com/netscaler/ansible-collection-netscaleradc/compare/2.8.0...2.9.0

Makefile

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,19 @@ fmt:
22
autoflake plugins/modules/*.py
33
autoflake plugins/module_utils/*.py
44
autoflake --recursive tests/
5+
autoflake tools/migrationtool/*.py
56

67
black plugins/modules/*.py
78
black plugins/module_utils/*.py
89
black tests/
10+
black tools/migrationtool/*.py
911

1012
isort plugins/modules/*.py
1113
isort plugins/module_utils/*.py
1214
isort tests/
15+
isort tools/migrationtool/*.py
1316

14-
yamlfmt .
17+
yamlfmt $(shell find . -name '*.yml' -o -name '*.yaml')
1518

1619
install:
1720
ansible-galaxy collection install . --force
@@ -39,7 +42,7 @@ build:
3942
ansible-galaxy collection build --force
4043

4144
galaxy_importer: build
42-
python3 -m galaxy_importer.main netscaler-adc-2.9.1.tar.gz
45+
python3 -m galaxy_importer.main netscaler-adc-2.10.1.tar.gz
4346

4447
# build_docs:
4548
# rm -rf _built_docs
@@ -60,7 +63,7 @@ galaxy_importer: build
6063
# skip the playbook which contains "password" in the file name
6164
run_examples:
6265
@for playbook in examples/*.yaml; do \
63-
if [[ $$playbook == *"password"* || $$playbook == *"login"* || $$playbook == *"logout"* || $$playbook == *"route"* || $$playbook == locationfile.yaml || $$playbook == nsip6.yaml || $$playbook == hanode.yaml ]]; then \
66+
if [[ $$playbook == *"password"* || $$playbook == *"login"* || $$playbook == *"logout"* || $$playbook == *"route"* || $$playbook == *"locationfile.yaml"* || $$playbook == *"nsip6.yaml"* || $$playbook == *"hanode.yaml"* ]]; then \
6467
continue; \
6568
fi; \
6669
echo "Running $$playbook"; \

README.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,62 @@ export NETSCALER_NITRO_AUTH_TOKEN=$(curl -X POST -H "Content-Type:application/js
157157
echo $echo $NETSCALER_NITRO_AUTH_TOKEN
158158
```
159159

160+
### Migration Tool
161+
162+
The collection includes a migration tool to help convert existing Ansible playbooks from the legacy `citrix.adc` collection to the new `netscaler.adc` collection format. This tool simplifies the transition from legacy automation to the updated collection.
163+
164+
#### Features
165+
166+
- **Module Mapping**: Automatically converts `citrix.adc` modules to `netscaler.adc` modules
167+
- **NITRO Request Conversion**: Transforms `citrix_adc_nitro_request` tasks to specific resource modules
168+
- **State Conversion**: Maps legacy operations (`add`, `update`, `delete`) to appropriate state values
169+
- **Credential Preservation**: Maintains authentication parameters and playbook structure
170+
- **YAML Structure Preservation**: Keeps task names, variables, and organization intact
171+
172+
#### Usage
173+
174+
```bash
175+
# Basic conversion
176+
python3 migrationtool/convert_yaml.py -i legacy_playbook.yaml -o migrated_playbook.yaml
177+
178+
# With verbose output
179+
python3 migrationtool/convert_yaml.py -i legacy_playbook.yaml -o migrated_playbook.yaml -v
180+
```
181+
182+
#### Example Conversion
183+
184+
**Before (Legacy citrix.adc):**
185+
```yaml
186+
- name: Configure LB vserver
187+
citrix_adc_nitro_request:
188+
nsip: "{{ nsip }}"
189+
nitro_user: "{{ nitro_user }}"
190+
nitro_pass: "{{ nitro_pass }}"
191+
operation: add
192+
resource: lbvserver
193+
name: my_lb_vserver
194+
attributes:
195+
servicetype: HTTP
196+
ipv46: 10.10.10.10
197+
port: 80
198+
```
199+
200+
**After (New netscaler.adc):**
201+
```yaml
202+
- name: Configure LB vserver
203+
netscaler.adc.lbvserver:
204+
nsip: "{{ nsip }}"
205+
nitro_user: "{{ nitro_user }}"
206+
nitro_pass: "{{ nitro_pass }}"
207+
state: present
208+
name: my_lb_vserver
209+
servicetype: HTTP
210+
ipv46: 10.10.10.10
211+
port: 80
212+
```
213+
214+
For detailed migration tool documentation, usage examples, and troubleshooting, refer to the [Migration Tool README](https://github.com/netscaler/ansible-collection-netscaleradc/blob/main/tools/migrationtool/README.md).
215+
160216
### Invocation
161217

162218
The credentials of the netscaler can be provided either in the playbook by hardcoding or defining in a inventory.ini file.

examples/bgprouter.yaml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
---
2+
- name: Sample bgprouter playbook
3+
hosts: localhost
4+
gather_facts: false
5+
tasks:
6+
- name: Configure bgprouter
7+
delegate_to: localhost
8+
netscaler.adc.bgprouter:
9+
state: present
10+
11+
localAS: 122
12+
routerId: "2.2.2.2"
13+
afParams:
14+
- addressFamily: "ipv4"
15+
redistribute:
16+
- protocol: "static"
17+
routeMap: "test"
18+
- addressFamily: "ipv6"
19+
neighbor:
20+
- address: "44.1.1.33"
21+
remoteAS: 300
22+
ASOriginationInterval: 11
23+
advertisementInterval: 34
24+
updateSource: "vlan101"
25+
singlehopBfd: false
26+
multihopBfd: false
27+
afParams:
28+
- addressFamily: "ipv4"
29+
routeMap:
30+
- name: "test"
31+
direction: "out"
32+
- addressFamily: "ipv6"

examples/sslhsmkey.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
- name: Create ssl hsm key
3+
hosts: localhost
4+
gather_facts: false
5+
tasks:
6+
- name: Create ssl hsm key
7+
delegate_to: localhost
8+
netscaler.adc.sslhsmkey:
9+
state: present
10+
hsmkeyname: "hsmk1"
11+
hsmtype: "SAFENET"
12+
serialnum: "116877xxxx465464"
13+
password: "xxxxxxx"

galaxy.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace: netscaler
77
# The name of the collection. Has the same character restrictions as 'namespace'
88
name: adc
99
# The version of the collection. Must be compatible with semantic versioning
10-
version: 2.9.2
10+
version: 2.10.1
1111
# The path to the Markdown (.md) readme file. This path is relative to the root of the collection
1212
readme: README.md
1313
# A list of the collection's content authors. Can be just the name or in the format 'Full Name <email> (url)
@@ -58,7 +58,6 @@ build_ignore:
5858
- ".DS_Store"
5959
- "docs"
6060
- "examples"
61-
- "tools"
6261
- "issues"
6362
- "**/netscaler-adc-*.tar.gz"
6463
- "Makefile"

meta/runtime.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -981,3 +981,4 @@ action_groups:
981981
- sslechconfig.py
982982
- sslhpkekey.py
983983
- sslprofile_sslechconfig_binding.py
984+
- bgprouter

plugins/module_utils/client.py

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@
1515
from ansible.module_utils.six.moves.urllib.parse import quote
1616
from ansible.module_utils.urls import fetch_url
1717

18-
from .constants import HTTP_SUCCESS_CODES
18+
from .constants import (
19+
DYNAMIC_PROTOCOLS,
20+
DYNAMIC_PROTOCOLS_ALIAS,
21+
HTTP_SUCCESS_CODES,
22+
)
1923
from .decorators import trace
2024
from .logger import log
2125

@@ -62,25 +66,25 @@ def __init__(self, module, resource_name):
6266
)
6367
if netscaler_console_as_proxy:
6468
if self._module.params.get("managed_netscaler_instance_name"):
65-
self._headers[
66-
"_MPS_API_PROXY_MANAGED_INSTANCE_NAME"
67-
] = self._module.params.get("managed_netscaler_instance_name")
69+
self._headers["_MPS_API_PROXY_MANAGED_INSTANCE_NAME"] = (
70+
self._module.params.get("managed_netscaler_instance_name")
71+
)
6872
if self._module.params.get("managed_netscaler_instance_ip"):
69-
self._headers[
70-
"_MPS_API_PROXY_MANAGED_INSTANCE_IP"
71-
] = self._module.params.get("managed_netscaler_instance_ip")
73+
self._headers["_MPS_API_PROXY_MANAGED_INSTANCE_IP"] = (
74+
self._module.params.get("managed_netscaler_instance_ip")
75+
)
7276
if self._module.params.get("managed_netscaler_instance_id"):
73-
self._headers[
74-
"_MPS_API_PROXY_MANAGED_INSTANCE_ID"
75-
] = self._module.params.get("managed_netscaler_instance_id")
77+
self._headers["_MPS_API_PROXY_MANAGED_INSTANCE_ID"] = (
78+
self._module.params.get("managed_netscaler_instance_id")
79+
)
7680
if self._module.params.get("managed_netscaler_instance_username"):
77-
self._headers[
78-
"_MPS_API_PROXY_MANAGED_INSTANCE_USERNAME"
79-
] = self._module.params.get("managed_netscaler_instance_username")
81+
self._headers["_MPS_API_PROXY_MANAGED_INSTANCE_USERNAME"] = (
82+
self._module.params.get("managed_netscaler_instance_username")
83+
)
8084
if self._module.params.get("managed_netscaler_instance_password"):
81-
self._headers[
82-
"_MPS_API_PROXY_MANAGED_INSTANCE_PASSWORD"
83-
] = self._module.params.get("managed_netscaler_instance_password")
85+
self._headers["_MPS_API_PROXY_MANAGED_INSTANCE_PASSWORD"] = (
86+
self._module.params.get("managed_netscaler_instance_password")
87+
)
8488

8589
@trace
8690
def url_builder(
@@ -98,6 +102,9 @@ def url_builder(
98102
filter = filter if filter is not None else {}
99103

100104
# Construct basic URL
105+
if resource in DYNAMIC_PROTOCOLS:
106+
resource = "routerDynamicRouting/" + DYNAMIC_PROTOCOLS_ALIAS[resource]
107+
101108
url = "%s://%s/%s/%s" % (
102109
self._module.params["nitro_protocol"],
103110
self._module.params["nsip"],
@@ -235,6 +242,7 @@ def post(self, post_data, resource, action=None):
235242
def put(self, put_data, resource=None, id=None):
236243
url = self.url_builder(resource, id=id)
237244
data = self._module.jsonify(put_data)
245+
238246
return self.send("PUT", url, data)
239247

240248
@trace

0 commit comments

Comments
 (0)