Skip to content

Add 'view' parameter to modules #319

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

Open
wants to merge 9 commits into
base: devel
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .ansible-lint
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright 2025 Cloudera, Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

profile: production
quiet: true
strict: true
verbosity: 1
offline: true
10 changes: 5 additions & 5 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ repos:
hooks:
- id: black
name: lint python
- repo: https://github.com/ansible/ansible-lint
rev: v25.6.1
hooks:
- id: ansible-lint
name: lint ansible
# - repo: https://github.com/ansible/ansible-lint
# rev: v25.6.1
# hooks:
# - id: ansible-lint
# name: lint ansible
31 changes: 31 additions & 0 deletions TESTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Testing

_For details on how to write integration tests and a deep dive into the testing utilities of the collection, check out the [README within the `tests` directory](./tests/README.md)._

The collection uses the [pytest](https://pytest.org) to run a set of integration tests for the majority of the modules and plugins. The tests require a functioning _minimally_ configured deployment of Cloudera Manager and its agents.

> [!IMPORANT]
> The Cloudera Manager Service nor a cluster are required for testing; the tests will construct the appropriate resources as needed.
>
> You must provide at minimum **three (3) servers** within the deployment.

All (or most of) the tests require the following environment variables:

- `CM_USERNAME`
- `CM_PASSWORD`
- `CDH_VERSION`

And either:

- `CM_HOST`
- `CM_PORT`

Or:

- `CM_ENDPOINT` (which is the full URL to the Cloudera Manager API endpoint)

Optionally,

- `CM_PROXY`

Running the tests from the CLI is simply a `pytest` execution.
2 changes: 1 addition & 1 deletion plugins/module_utils/cm_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,7 @@ def call_api(self, path, method, query=None, field="items", body=None):
data = data[field]
return data if isinstance(data, list) else [data]

def get_cm_config(self, scope: str = "summary") -> ApiConfigList:
def get_cm_config(self, scope: str = "full") -> list[ApiConfig]:
return ClouderaManagerResourceApi(self.api_client).get_config(view=scope).items

def wait_command(self, command: ApiCommand, polling: int = 10, delay: int = 5):
Expand Down
7 changes: 5 additions & 2 deletions plugins/module_utils/host_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def get_host(
api_client: ApiClient,
hostname: str = None,
host_id: str = None,
view: str = "summary",
view: str = "full",
) -> ApiHost:
"""Retrieve a Host by either hostname or host ID.

Expand Down Expand Up @@ -172,6 +172,7 @@ def get_host_ref(
api_client: ApiClient,
hostname: str = None,
host_id: str = None,
view: str = "full",
) -> ApiHostRef:
"""Retrieve a Host Reference by either hostname or host ID.

Expand All @@ -186,7 +187,7 @@ def get_host_ref(
Returns:
ApiHostRef: Host reference object. If not found, returns None.
"""
host = get_host(api_client, hostname, host_id)
host = get_host(api_client, hostname, host_id, view)

if host is not None:
return ApiHostRef(host.host_id, host.hostname)
Expand Down Expand Up @@ -249,6 +250,7 @@ def reconcile_host_role_configs(
check_mode: bool,
skip_redacted: bool,
message: str = None,
view: str = "full",
) -> tuple[list[dict], list[dict]]:

diff_before, diff_after = list[dict](), list[dict]()
Expand All @@ -265,6 +267,7 @@ def reconcile_host_role_configs(
service_name=incoming_role_config["service"],
type=incoming_role_config["type"],
host_id=host.host_id,
view=view,
).items,
),
None,
Expand Down
24 changes: 14 additions & 10 deletions plugins/module_utils/role_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ def read_role(
cluster_name: str,
service_name: str,
role_name: str,
view: str = "full",
) -> ApiRole:
"""Read a role for a cluster service and populates the role configuration.

Expand All @@ -120,6 +121,7 @@ def read_role(
cluster_name (str): Cluster name (identifier).
service_name (str): Service name (identifier).
role_name (str): Role name (identifier).
view (str, optional): View to retrieve. Defaults to 'full'.

Raises:
ApiException:
Expand All @@ -132,12 +134,14 @@ def read_role(
cluster_name=cluster_name,
service_name=service_name,
role_name=role_name,
view=view,
)
if role is not None:
role.config = role_api.read_role_config(
cluster_name=cluster_name,
service_name=service_name,
role_name=role.name,
view=view,
)
return role

Expand All @@ -149,7 +153,7 @@ def read_roles(
type: str = None,
hostname: str = None,
host_id: str = None,
view: str = None,
view: str = "full",
) -> ApiRoleList:
"""Read roles for a cluster service. Optionally, filter by type, hostname, host ID.

Expand All @@ -160,7 +164,7 @@ def read_roles(
type (str, optional): Role type. Defaults to None.
hostname (str, optional): Cluster hostname. Defaults to None.
host_id (str, optional): Cluster host ID. Defaults to None.
view (str, optional): View to retrieve. Defaults to None.
view (str, optional): View to retrieve. Defaults to 'full'.

Raises:
ApiException:
Expand All @@ -173,11 +177,9 @@ def read_roles(
payload = dict(
cluster_name=cluster_name,
service_name=service_name,
view=view,
)

if view is not None:
payload.update(view=view)

filter = ";".join(
[
f"{f[0]}=={f[1]}"
Expand Down Expand Up @@ -210,38 +212,40 @@ def read_roles_by_type(
cluster_name: str,
service_name: str,
role_type: str,
view: str = "full",
) -> ApiRoleList:
role_api = RolesResourceApi(api_client)
roles = [
r
for r in role_api.read_roles(cluster_name, service_name).items
for r in role_api.read_roles(cluster_name, service_name, view=view).items
if r.type == role_type
]
for r in roles:
r.config = role_api.read_role_config(
cluster_name=cluster_name,
service_name=service_name,
role_name=r.name,
view=view,
)
return ApiRoleList(items=roles)


def read_cm_role(api_client: ApiClient, role_type: str) -> ApiRole:
def read_cm_role(api_client: ApiClient, role_type: str, view: str = "full") -> ApiRole:
role_api = MgmtRolesResourceApi(api_client)
role = next(
iter([r for r in role_api.read_roles().items if r.type == role_type]),
None,
)
if role is not None:
role.config = role_api.read_role_config(role.name)
role.config = role_api.read_role_config(role_name=role.name, view=view)
return role


def read_cm_roles(api_client: ApiClient) -> ApiRoleList:
def read_cm_roles(api_client: ApiClient, view: str = "full") -> ApiRoleList:
role_api = MgmtRolesResourceApi(api_client)
roles = role_api.read_roles().items
for r in roles:
r.config = role_api.read_role_config(role_name=r.name)
r.config = role_api.read_role_config(role_name=r.name, view=view)
return ApiRoleList(items=roles)


Expand Down
Loading
Loading