Skip to content

Commit

Permalink
Run ansible sanity with all python versions and with latest ansible v…
Browse files Browse the repository at this point in the history
…ersions (#573)
  • Loading branch information
bhati-pradeep authored Jan 8, 2025
1 parent d6e75e7 commit 51e2d8a
Show file tree
Hide file tree
Showing 16 changed files with 46 additions and 161 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ansible-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ jobs:
- name: Set up Python 3.x (latest)
uses: actions/setup-python@v2
with:
python-version: 3.9
python-version: 3.x
- name: Run ansible-lint
uses: ansible/ansible-lint@main
16 changes: 8 additions & 8 deletions .github/workflows/unit_testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ on:
- pull_request
jobs:
sanity1:
name: Sanity tests with ansible-core==2.15.0
runs-on: ubuntu-20.04
name: Sanity tests
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9"]
python-version: ["3.11"]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
Expand All @@ -27,7 +27,7 @@ jobs:
uses: docker-practice/actions-setup-docker@master
- name: Install ansible
run: |
pip install -r requirements.txt
pip install -r tests/integration/requirements.txt
- name: Build and install the collection
run: |
NAMESPACE=$(cat galaxy.yml | shyaml get-value namespace)
Expand All @@ -40,12 +40,12 @@ jobs:
- name: Run tests
run: |
cd /home/${USER}/.ansible/collections/ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }}
ansible-test sanity --docker default --python ${{ matrix.python-version }} -v
ansible-test sanity --docker default -v
unit_testing:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9"]
python-version: ["3.11"]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
Expand All @@ -56,7 +56,7 @@ jobs:
uses: docker-practice/actions-setup-docker@master
- name: Install ansible
run: |
pip install -r requirements.txt
pip install -r tests/integration/requirements.txt
- name: Build and install the collection
run: |
NAMESPACE=$(cat galaxy.yml | shyaml get-value namespace)
Expand Down
6 changes: 4 additions & 2 deletions galaxy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ authors:
- "Prem Karat (@premkarat)"
- "Gevorg Khachatryan (@Gevorg-Khachatryan-97)"
- "Alaa Bishtawi (@alaa-bish)"
description: Ansible collection for v3 Nutanix APIs https://www.nutanix.dev/api-reference-v3/
- "Abhinav Bansal (@abhinavbansal29)"
- "George Ghawali (@george-ghawali)"
description: Nutanix Ansible Collection
license_file: 'LICENSE'
tags: [nutanix, prism, ahv, cloud, infrastructure]
repository: https://github.com/nutanix/nutanix.ansible
documentation: https://nutanix.github.io/nutanix.ansible/
documentation: https://galaxy.ansible.com/ui/repo/published/nutanix/ncp/
homepage: https://nutanix.github.io/nutanix.ansible/
issues: https://github.com/nutanix/nutanix.ansible/issues
build_ignore: []
114 changes: 5 additions & 109 deletions plugins/module_utils/v3/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,110 +20,6 @@
from urlparse import urlparse # python2


class EntityV4(object):
module = None

def __init__(self, module):
self.module = module

# old_spec is used for updating entity, where there is already spec object present.
def get_spec(self, module_args, params=None, obj=None, old_spec=None):
"""
For given module parameters input, it will create new spec object or update old_spec object.
It will pick module.params if 'params' is not given.
Args:
module_args (dict): module argument spec for reference
obj (object): spec class from sdk
params (dict): input for creating spec
old_spec (object): Old state obj of entity
Returns:
spec (object): spec object
"""

if not params:
params = copy.deepcopy(self.module.params)

if not old_spec and not obj:
return (
None,
"Either 'old_spec' or 'obj' is required to create/update spec object",
)

# create spec obj or shallow copy of old spec as per entity spec - new or existing
spec = copy.copy(old_spec) if old_spec else obj()

# Resolve each input param w.r.t its module argument spec
for attr, schema in module_args.items():

if attr in params:

type = schema.get("type")
if not type:
return (
None,
"Invalid module argument: 'type' is required parameter for attribute {0}".format(
attr
),
)

options = schema.get("options")
_obj = schema.get("obj")
elements = schema.get("elements")

# for dict type attribute, recursively create spec objects
if type == "dict" and options is not None and _obj is not None:
s, err = self.get_spec(
module_args=options,
obj=_obj,
params=params[attr],
old_spec=getattr(spec, attr),
)
if err:
return None, err
setattr(spec, attr, s)

# for list type attribute, create list of spec objects recursively
elif (
type == "list"
and elements == "dict"
and options is not None
and _obj is not None
):
lst = []
for item in params[attr]:
s, err = self.get_spec(
module_args=options, obj=_obj, params=item
)
if err:
return None, err
lst.append(s)
setattr(spec, attr, lst)

# for other types directly assign
else:
setattr(spec, attr, params[attr])

return spec, None

def get_info_spec(self, params=None):

if not params:
params = copy.deepcopy(self.module.params)
spec = {}
all_params = ["page", "limit", "filter", "orderby", "select"]
if params.get("name"):
_filter = params.get("filter")
if _filter:
_filter += f"""and name eq '{params["name"]}'"""
else:
_filter = f"""name eq '{params["name"]}'"""
params["filter"] = _filter
for key, val in params.items():
if key in all_params:
spec[f"_{key}"] = val
return spec


class Entity(object):
entities_limitation = 20
entity_type = "entities"
Expand Down Expand Up @@ -172,7 +68,7 @@ def read(
no_response=False,
timeout=30,
method="GET",
**kwargs,
**kwargs # fmt: skip
):
url = self.base_url + "/{0}".format(uuid) if uuid else self.base_url
if endpoint:
Expand All @@ -185,7 +81,7 @@ def read(
raise_error=raise_error,
no_response=no_response,
timeout=timeout,
**kwargs,
**kwargs # fmt: skip
)

def update(
Expand All @@ -198,7 +94,7 @@ def update(
no_response=False,
timeout=30,
method="PUT",
**kwargs,
**kwargs # fmt: skip
):
url = self.base_url + "/{0}".format(uuid) if uuid else self.base_url
if endpoint:
Expand All @@ -212,7 +108,7 @@ def update(
raise_error=raise_error,
no_response=no_response,
timeout=timeout,
**kwargs,
**kwargs # fmt: skip
)

# source is the file path of resource where ansible yaml runs
Expand Down Expand Up @@ -458,7 +354,7 @@ def _fetch_url(
raise_error=True,
no_response=False,
timeout=30,
**kwargs,
**kwargs # fmt: skip
):
# only jsonify if content-type supports, added to avoid incase of form-url-encodeded type data
if self.headers["Content-Type"] == "application/json" and data is not None:
Expand Down
4 changes: 3 additions & 1 deletion plugins/module_utils/v3/foundation/discover_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ def discover(self, include_configured=False):
result_nodes = []
for n in nodes:
configured = n.get("configured")
if include_configured or (type(configured) == bool and not configured):
if include_configured or (
isinstance(configured, bool) and not configured
):

# handle datatype corner cases for cluster_id & current_cvm_vlan_tag
if n.get("cluster_id"):
Expand Down
6 changes: 3 additions & 3 deletions plugins/module_utils/v4/spec_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,13 @@ def get_info_spec(self, attr=None, extra_params=None):
if attr.get("name"):
_filter = attr.get("filter")
if _filter:
_filter += f"""and name eq '{attr["name"]}'"""
_filter += "and name eq '{0}'".format(attr["name"])
else:
_filter = f"""name eq '{attr["name"]}'"""
_filter = "name eq '{0}'".format(attr["name"])
attr["filter"] = _filter
for key, val in attr.items():
if key in all_params:
spec[f"_{key}"] = val
spec["_{0}".format(key)] = val
return spec, None

def get_stats_spec(self, attr=None):
Expand Down
6 changes: 2 additions & 4 deletions plugins/modules/ntnx_authorization_policies_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,10 +386,8 @@ def update_authorization_policy(module, result):

if getattr(resp.data, "severity", None) == "ERROR":
result["error"] = resp.data.message
module.fail_json(
msg="Failed to update authorization policy",
**result,
)
msg = "Failed to update authorization policy"
module.fail_json(msg=msg, **result)

resp = get_authorization_policy(module, authorization_policies, ext_id=ext_id)
result["response"] = strip_internal_attributes(resp.to_dict())
Expand Down
2 changes: 1 addition & 1 deletion plugins/modules/ntnx_discover_unconfigured_nodes_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ def discover_unconfigured_cluster_node(module, cluster_node_api, result):
result["error"] = err
module.fail_json(
msg="Failed generating spec for fetching prism central cluster",
**result,
**result # fmt: skip
)
try:
pc_cluster = cluster_node_api.list_clusters(**kwargs)
Expand Down
6 changes: 1 addition & 5 deletions plugins/modules/ntnx_gpus_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,11 +235,7 @@ def detach_gpu(module, vms, result):
kwargs = {"if_match": etag}

try:
resp = vms.delete_gpu_by_id(
vmExtId=vm_ext_id,
extId=ext_id,
**kwargs,
)
resp = vms.delete_gpu_by_id(vmExtId=vm_ext_id, extId=ext_id, **kwargs)
except Exception as e:
raise_api_exception(
module=module,
Expand Down
6 changes: 2 additions & 4 deletions plugins/modules/ntnx_image_placement_policies_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,10 +390,8 @@ def update_policy_state(module, result, policies, ext_id):
policy = get_policy(module, policies, ext_id)
etag = get_etag(data=policy)
if not etag:
return module.fail_json(
"unable to fetch etag for updating Placement Policy enforcement state",
**result,
)
msg = "unable to fetch etag for updating Placement Policy enforcement state"
return module.fail_json(msg, **result)

kwargs = {"if_match": etag}
resp = None
Expand Down
6 changes: 2 additions & 4 deletions plugins/modules/ntnx_nodes_network_info_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,10 +382,8 @@ def get_nodes_network_information(module, cluster_node_api, result):
spec, err = sg.generate_spec(default_spec)
if err:
result["error"] = err
module.fail_json(
msg="Failed generating spec for getting network information for cluster nodes",
**result,
)
msg = "Failed generating spec for getting network information for cluster nodes"
module.fail_json(msg=msg, **result)
cluster_ext_id = module.params.get("cluster_ext_id")
result["cluster_ext_id"] = cluster_ext_id
if module.check_mode:
Expand Down
12 changes: 4 additions & 8 deletions plugins/modules/ntnx_pbrs_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -812,10 +812,8 @@ def get_routing_policy_ext_id(module, result, api_instance, vpc_ext_id, priority
kwargs, err = sg.get_info_spec(attr=params)
if err:
result["error"] = err
module.fail_json(
msg="Failed generating spec for fetching routing policy using priority and vpc_ext_id",
**result,
)
msg = "Failed generating spec for fetching routing policy using priority and vpc_ext_id"
module.fail_json(msg=msg, **result)

try:
resp = api_instance.list_routing_policies(**kwargs)
Expand All @@ -834,10 +832,8 @@ def get_routing_policy_ext_id(module, result, api_instance, vpc_ext_id, priority

def create_pbr(module, result):
if not module.params.get("vpc_ext_id") and module.params.get("priority"):
module.fail_json(
msg="vpc_ext_id and priority are required for creating routing policy",
**result,
)
msg = "vpc_ext_id and priority are required for creating routing policy"
module.fail_json(msg=msg, **result)

pbrs = get_routing_policies_api_instance(module)

Expand Down
6 changes: 2 additions & 4 deletions plugins/modules/ntnx_recovery_points_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,10 +405,8 @@ def update_expiry_date_recovery_point(module, result):
old_spec.to_dict(), update_spec.to_dict()
):
result["skipped"] = True
module.exit_json(
msg="Update of other operations is not supported. Only updation of Expiration time is allowed.",
**result,
)
msg = "Update of other operations is not supported. Only updation of Expiration time is allowed."
module.exit_json(msg=msg, **result)
else:
result["skipped"] = True
module.exit_json(msg="Nothing to change.", **result)
Expand Down
5 changes: 4 additions & 1 deletion plugins/modules/ntnx_templates_deploy_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,10 @@ def deploy_template(module, result):
version_ext_id = module.params.get("version_id")
result[
"msg"
] = f"Template ({ext_id}) with given version ({version_ext_id}) will be deployed."
] = "Template ({0}) with given version ({1}) will be deployed.".format(
ext_id,
version_ext_id # fmt: skip
)
return

etag = get_etag(data=current_spec)
Expand Down
6 changes: 2 additions & 4 deletions plugins/modules/ntnx_vms_stage_guest_customization_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,10 +283,8 @@ def stage_customize_guest(module, result):

if err:
result["error"] = err
module.fail_json(
msg="Failed generating stage guest customization configuration spec",
**result,
)
msg = "Failed generating stage guest customization configuration spec"
module.fail_json(msg=msg, **result)

if module.check_mode:
result["response"] = strip_internal_attributes(spec.to_dict())
Expand Down
4 changes: 2 additions & 2 deletions tests/integration/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
pip~=21.3.1
ipaddress~=1.0.23
setuptools~=44.1.1
ansible-core==2.15.0
ansible-core==2.16.0
requests~=2.26.0
black==22.8.0
flake8==4.0.1
isort==5.9.3
coverage==6.5.0
coverage==7.3.2
shyaml==0.6.2
markupsafe==2
ntnx-clustermgmt-py-client==4.0.1
Expand Down

0 comments on commit 51e2d8a

Please sign in to comment.