Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9461ee6
Fix get_service_hosts()
wmudge Apr 2, 2025
2835f0f
Add try/catch for deregistering non-existent services
wmudge Apr 2, 2025
e0c2bd9
Add utilities for creating models, provisioning, and updating role co…
wmudge Apr 7, 2025
de0f09b
Add check for invalid role type when creating a role model
wmudge Apr 7, 2025
edd55cc
Add utilities for creating models, provisioning, and reconciing role …
wmudge Apr 7, 2025
33e0634
Update service module to handle service-wide configuration and core f…
wmudge Apr 7, 2025
0cf3d2a
Add try/except to handle previously deleted role config groups
wmudge Apr 7, 2025
34f91ce
Update tests for service role to use pytest fixtures.
wmudge Apr 7, 2025
c88697c
Rename role exceptions
wmudge Apr 9, 2025
a7f6cb6
Add reconcile_service_roles() utility function
wmudge Apr 9, 2025
2f80182
Update for reconciling existing roles and state.
wmudge Apr 9, 2025
f4e730b
Add missing tests and skip legacy tests
wmudge Apr 9, 2025
1d178d3
Fix errors with tag and role config group reconciliation and role cre…
wmudge Apr 10, 2025
329b650
Add create roles
wmudge Apr 10, 2025
db3a94f
Check for running commands on and stop running services before deletion
wmudge Apr 10, 2025
4e0622e
Add resettable_cluster fixture
wmudge Apr 10, 2025
47e3e00
Remove legacy tests
wmudge Apr 10, 2025
50a5a24
Enable restarted state and test all states
wmudge Apr 10, 2025
96718e6
Add additional action_groups for module defaults
wmudge Apr 10, 2025
87c66a9
Update documentation, examples, and return values.
wmudge Apr 17, 2025
34f0984
Remove service_name from role_config_group and roles return values
wmudge Apr 17, 2025
fde3b88
Update docstring for parse_role_config_group_result
wmudge Apr 17, 2025
2c94c67
Add required role_type parameter to tests
wmudge Apr 17, 2025
523475b
Remove unused function
wmudge Apr 17, 2025
2e8e613
Add read_services() utility function
wmudge Apr 17, 2025
22fe2c8
Remove obsolete test
wmudge Apr 17, 2025
67ca892
Update service_info module to align with utilities and output
wmudge Apr 17, 2025
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
46 changes: 46 additions & 0 deletions meta/runtime.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,49 @@ action_groups:
- cm
- cluster_info
- cluster
service:
- metadata:
extend_group:
- cm
- service_info
- service
role:
- metadata:
extend_group:
- cm
- service_role_info
- service_role
role_config_group:
- metadata:
extend_group:
- cm
- service_role_config_group_info
- service_role_config_group
host:
- metadata:
extend_group:
- cm
- host_info
- host
host_template:
- metadata:
extend_group:
- cm
- host_template_info
- host_template
parcel:
- metadata:
extend_group:
- cm
- parcel_info
- parcel
deployment:
- metadata:
extend_group:
- cluster
- service
- role
- role_config_group
- host
- host_template
- parcel
1 change: 1 addition & 0 deletions plugins/module_utils/cluster_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ def parse_cluster_result(cluster: ApiCluster) -> dict:
return output


# TODO Convert to use cluster_name vs the ApiCluster object for broader usage in pytest fixtures
def get_cluster_hosts(api_client: ApiClient, cluster: ApiCluster) -> list[ApiHost]:
return (
ClustersResourceApi(api_client)
Expand Down
119 changes: 105 additions & 14 deletions plugins/module_utils/role_config_group_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,20 @@

from ansible_collections.cloudera.cluster.plugins.module_utils.cm_utils import (
normalize_output,
ConfigListUpdates,
)
from ansible_collections.cloudera.cluster.plugins.module_utils.role_utils import (
InvalidRoleTypeException,
)

from cm_client import (
ApiClient,
ApiConfig,
ApiConfigList,
ApiRoleConfigGroup,
ApiRoleConfigGroupList,
RoleConfigGroupsResourceApi,
ServicesResourceApi,
MgmtRoleConfigGroupsResourceApi,
)

Expand All @@ -41,6 +49,7 @@ def parse_role_config_group_result(role_config_group: ApiRoleConfigGroup) -> dic
- base (bool)
- display_name (str)
- config (dict)
- service_name (str)

Args:
role_config_group (ApiRoleConfigGroup): Role Config Group
Expand All @@ -55,23 +64,105 @@ def parse_role_config_group_result(role_config_group: ApiRoleConfigGroup) -> dic
return output


def get_base_role_config_group(
api_client: ApiClient, cluster_name: str, service_name: str, role_type: str
def create_role_config_group(
api_client: ApiClient,
cluster_name: str,
service_name: str,
name: str,
role_type: str,
display_name: str = None,
config: dict = None,
) -> ApiRoleConfigGroup:
rcg_api = RoleConfigGroupsResourceApi(api_client)
return next(
iter(
[
r
for r in rcg_api.read_role_config_groups(
cluster_name, service_name
).items
if r.role_type == role_type and r.base
]
),
None,
if (
role_type.upper()
not in ServicesResourceApi(api_client)
.list_role_types(
cluster_name=cluster_name,
service_name=service_name,
)
.items
):
raise InvalidRoleTypeException(
f"Invalid role type '{role_type}' for service '{service_name}'"
)

role_config_group = ApiRoleConfigGroup(
name=name,
role_type=role_type.upper(),
)

if display_name:
role_config_group.display_name = display_name

if config:
role_config_group.config = ApiConfigList(
items=[ApiConfig(name=k, value=v) for k, v in config.items()]
)

return role_config_group


def provision_role_config_groups(
api_client: ApiClient,
cluster_name: str,
service_name: str,
role_config_groups: list[ApiRoleConfigGroup],
) -> ApiRoleConfigGroup:
return RoleConfigGroupsResourceApi(api_client).create_role_config_groups(
cluster_name=cluster_name,
service_name=service_name,
body=ApiRoleConfigGroupList(items=role_config_groups),
)


def update_role_config_group(
role_config_group: ApiRoleConfigGroup,
display_name: str = None,
config: dict = None,
purge: bool = False,
) -> tuple[ApiRoleConfigGroup, dict, dict]:
before, after = dict(), dict()

# Check for display name changes
if display_name is not None and display_name != role_config_group.display_name:
before.update(display_name=role_config_group.display_name)
after.update(display_name=display_name)
role_config_group.display_name = display_name

# Reconcile configurations
if config or purge:
if config is None:
config = dict()

updates = ConfigListUpdates(role_config_group.config, config, purge)

if updates.changed:
before.update(config=updates.diff["before"])
after.update(config=updates.diff["after"])
role_config_group.config = updates.config

return (role_config_group, before, after)


# TODO Normalize the return value to be a list
def get_base_role_config_group(
api_client: ApiClient, cluster_name: str, service_name: str, role_type: str = None
) -> ApiRoleConfigGroup:
base_rcg_list = [
r
for r in RoleConfigGroupsResourceApi(api_client)
.read_role_config_groups(
cluster_name=cluster_name,
service_name=service_name,
)
.items
if (r.base and role_type is None) or (r.base and r.role_type == role_type)
]
if role_type is not None:
return next(iter(base_rcg_list), None)
else:
return base_rcg_list


def get_mgmt_base_role_config_group(
api_client: ApiClient, role_type: str
Expand Down
45 changes: 31 additions & 14 deletions plugins/module_utils/role_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
ApiRoleConfigGroupRef,
ApiRoleNameList,
ApiRoleState,
ServicesResourceApi,
RoleCommandsResourceApi,
RoleConfigGroupsResourceApi,
RolesResourceApi,
Expand All @@ -47,6 +48,22 @@ class RoleException(Exception):
pass


class RoleHostNotFoundException(RoleException):
pass


class RoleConfigGroupNotFoundException(RoleException):
pass


class RoleMaintenanceStateException(RoleException):
pass


class InvalidRoleTypeException(RoleException):
pass


ROLE_OUTPUT = [
"commission_state",
"config_staleness_status",
Expand Down Expand Up @@ -214,14 +231,6 @@ def read_cm_roles(api_client: ApiClient) -> ApiRoleList:
return ApiRoleList(items=roles)


class HostNotFoundException(RoleException):
pass


class RoleConfigGroupNotFoundException(RoleException):
pass


def create_role(
api_client: ApiClient,
role_type: str,
Expand All @@ -233,14 +242,26 @@ def create_role(
role_config_group: str = None,
tags: dict = None,
) -> ApiRole:
if (
role_type.upper()
not in ServicesResourceApi(api_client)
.list_role_types(
cluster_name=cluster_name,
service_name=service_name,
)
.items
):
raise InvalidRoleTypeException(
f"Invalid role type '{role_type}' for service '{service_name}'"
)

# Set up the role type
role = ApiRole(type=str(role_type).upper())

# Host assignment
host_ref = get_host_ref(api_client, hostname, host_id)
if host_ref is None:
raise HostNotFoundException(
raise RoleHostNotFoundException(
f"Host not found: hostname='{hostname}', host_id='{host_id}'"
)
else:
Expand Down Expand Up @@ -315,10 +336,6 @@ def provision_service_role(
raise RoleException(str(e))


class MaintenanceStateException(RoleException):
pass


def toggle_role_maintenance(
api_client: ApiClient, role: ApiRole, maintenance: bool, check_mode: bool
) -> bool:
Expand All @@ -340,7 +357,7 @@ def toggle_role_maintenance(
)

if maintenance_cmd.success is False:
raise MaintenanceStateException(
raise RoleMaintenanceStateException(
f"Unable to set Maintenance mode to '{maintenance}': {maintenance_cmd.result_message}"
)

Expand Down
Loading
Loading