Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run ansible sanity with all python versions and with latest ansible versions #573

Merged
merged 16 commits into from
Jan 8, 2025
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
Loading