Skip to content

Commit 4e9910c

Browse files
authored
Update parcel_info API output and move parsing function to parcel_utils (#226)
Signed-off-by: Webster Mudge <wmudge@cloudera.com>
1 parent 91d2083 commit 4e9910c

File tree

6 files changed

+172
-101
lines changed

6 files changed

+172
-101
lines changed

plugins/module_utils/cm_utils.py

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
ApiClient,
3636
ApiCommand,
3737
ApiConfigList,
38-
ApiParcel,
3938
ApiRole,
4039
ApiRoleConfigGroup,
4140
Configuration,
@@ -74,16 +73,6 @@
7473
# "service_ref",
7574
]
7675

77-
PARCEL = [
78-
"product",
79-
"version",
80-
"stage",
81-
# "cluster_ref",
82-
"state",
83-
"display_name",
84-
"description",
85-
]
86-
8776

8877
def _parse_output(entity: dict, filter: list) -> dict:
8978
output = {}
@@ -114,13 +103,6 @@ def parse_role_config_group_result(role_config_group: ApiRoleConfigGroup) -> dic
114103
return output
115104

116105

117-
def parse_parcel_result(parcel: ApiParcel) -> dict:
118-
# Retrieve only the cluster identifier
119-
output = dict(cluster_name=parcel.cluster_ref.cluster_name)
120-
output.update(_parse_output(parcel.to_dict(), PARCEL))
121-
return output
122-
123-
124106
def normalize_values(add: dict) -> dict:
125107
"""Normalize whitespace of parameter values.
126108

plugins/module_utils/parcel_utils.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@
2020

2121
from enum import IntEnum
2222

23-
from cm_client import ParcelResourceApi
23+
from cm_client import ApiParcel, ParcelResourceApi
24+
25+
from ansible_collections.cloudera.cluster.plugins.module_utils.cm_utils import (
26+
_parse_output,
27+
)
2428

2529

2630
class Parcel(object):
@@ -118,3 +122,21 @@ def activate(self):
118122
elif self.current < self.STAGE.ACTIVATED:
119123
self.distribute(self.STAGE.ACTIVATED)
120124
self._exec(self.STAGE.ACTIVATED, self.parcel_api.activate_command)
125+
126+
127+
PARCEL = [
128+
"product",
129+
"version",
130+
"stage",
131+
# "cluster_ref",
132+
"state",
133+
"display_name",
134+
"description",
135+
]
136+
137+
138+
def parse_parcel_result(parcel: ApiParcel) -> dict:
139+
# Retrieve only the cluster identifier
140+
output = dict(cluster_name=parcel.cluster_ref.cluster_name)
141+
output.update(_parse_output(parcel.to_dict(), PARCEL))
142+
return output

plugins/modules/parcel.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414

1515
from ansible_collections.cloudera.cluster.plugins.module_utils.cm_utils import (
1616
ClouderaManagerModule,
17-
parse_parcel_result,
1817
)
1918

2019
from ansible_collections.cloudera.cluster.plugins.module_utils.parcel_utils import (
2120
Parcel,
21+
parse_parcel_result,
2222
)
2323

2424
from cm_client import ClustersResourceApi, ParcelResourceApi
@@ -31,7 +31,6 @@
3131
}
3232

3333
DOCUMENTATION = r"""
34-
---
3534
module: parcel
3635
short_description: Manage the state of parcels on a cluster
3736
description:
@@ -43,25 +42,30 @@
4342
requirements:
4443
- cm-client
4544
options:
46-
cluster_name:
45+
cluster:
4746
description:
4847
- The name of the cluster
4948
type: str
5049
required: yes
51-
product:
50+
aliases:
51+
- cluster_name
52+
name:
5253
description:
5354
- The name of the product, e.g. CDH, Impala
5455
type: str
5556
required: yes
56-
version:
57+
aliases:
58+
- parcel
59+
- product
60+
parcel_version:
5761
description:
5862
- The semantic version of the product, e.g. 1.1.0, 2.3.0.
5963
type: str
6064
required: yes
6165
state:
6266
description:
6367
- State of the parcel.
64-
- I(present) is the same as I(activated).
68+
- I(present) is mapped to I(activated).
6569
type: str
6670
default: 'present'
6771
choices:
@@ -85,7 +89,6 @@
8589
"""
8690

8791
EXAMPLES = r"""
88-
---
8992
- name: Download, distribute and activate a parcel on a cluster
9093
cloudera.cluster.parcel:
9194
host: example.cloudera.com
@@ -124,12 +127,10 @@
124127
cluster_name: "Example_Cluster"
125128
product: "ECS"
126129
parcel_version: "1.5.1-b626-ecs-1.5.1-b626.p0.42068229"
127-
state: "downloaded" # Assuming the current state as stated above
128-
130+
state: "downloaded" # Assuming the current state is "distributed" or "activated"
129131
"""
130132

131133
RETURN = r"""
132-
---
133134
parcel:
134135
description: Details about the parcel
135136
type: dict
@@ -181,7 +182,7 @@ def __init__(self, module):
181182

182183
# Set parameters
183184
self.cluster = self.get_param("cluster")
184-
self.parcel_name = self.get_param("parcel")
185+
self.parcel_name = self.get_param("name")
185186
self.parcel_version = self.get_param("parcel_version")
186187
self.state = self.get_param("state")
187188
self.delay = self.get_param("delay")
@@ -204,7 +205,7 @@ def process(self):
204205
cluster_api.read_cluster(cluster_name=self.cluster).to_dict()
205206
except ApiException as ex:
206207
if ex.status == 404:
207-
self.module.fail_json(msg=f" Cluster {self.cluster} {ex.reason}")
208+
self.module.fail_json(msg=f" Cluster '{self.cluster}' not found")
208209

209210
try:
210211
parcel = Parcel(
@@ -252,7 +253,7 @@ def main():
252253
module = ClouderaManagerModule.ansible_module(
253254
argument_spec=dict(
254255
cluster=dict(required=True, aliases=["cluster_name"]),
255-
parcel=dict(required=True, aliases=["parcel_name", "product", "name"]),
256+
name=dict(required=True, aliases=["parcel", "product"]),
256257
parcel_version=dict(required=True),
257258
delay=dict(
258259
required=False, type="int", default=10, aliases=["polling_interval"]

plugins/modules/parcel_info.py

Lines changed: 53 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
ClouderaManagerModule,
1717
)
1818

19+
from ansible_collections.cloudera.cluster.plugins.module_utils.parcel_utils import (
20+
parse_parcel_result,
21+
)
22+
1923
from cm_client import ClustersResourceApi, ParcelResourceApi, ParcelsResourceApi
2024
from cm_client.rest import ApiException
2125

@@ -26,35 +30,40 @@
2630
}
2731

2832
DOCUMENTATION = r"""
29-
---
3033
module: parcel_info
3134
short_description: Gather details about the parcels on the cluster
3235
description:
3336
- Gathers details about a single parcel or about all parcels on the cluster
3437
author:
3538
- "Ronald Suplina (@rsuplina)"
3639
requirements:
37-
- cm_client
40+
- cm-client
3841
options:
39-
cluster_name:
42+
cluster:
4043
description:
4144
- The name of the cluster
4245
type: str
4346
required: yes
44-
product:
47+
aliases:
48+
- cluster_name
49+
name:
4550
description:
46-
- The name of the product, e.g. CDH, Impala
51+
- The name of the product, e.g. CDH, Impala.
52+
- Required if I(parcel_version) is declared.
4753
type: str
4854
required: no
55+
aliases:
56+
- product
57+
- parcel
4958
parcel_version:
5059
description:
5160
- The version of the product, e.g. 1.1.0, 2.3.0.
61+
- Required if I(name) is declared.
5262
type: str
5363
required: no
5464
"""
5565

5666
EXAMPLES = r"""
57-
---
5867
- name: Gather details about specific parcel
5968
cloudera.cluster.parcel_info:
6069
host: example.cloudera.com
@@ -73,9 +82,8 @@
7382
"""
7483

7584
RETURN = r"""
76-
---
77-
cloudera_manager:
78-
description: Returns details about specific parcel or all parcels on the cluster
85+
parcels:
86+
description: Returns details about a specific parcel or all parcels on the cluster
7987
type: list
8088
elements: dict
8189
contains:
@@ -94,14 +102,14 @@
94102
state:
95103
description:
96104
- The state of the parcel.
97-
- Shows the progress of state transitions and reports any errors.
105+
- This shows the progress of state transitions and if there were any errors.
98106
type: dict
99107
returned: when supported
100108
cluster_name:
101109
description: The name of the enclosing cluster.
102110
type: dict
103111
returned: always
104-
displayName:
112+
display_name:
105113
description: Display name of the parcel.
106114
type: str
107115
returned: when supported
@@ -115,59 +123,65 @@
115123
class ClouderaParcelInfo(ClouderaManagerModule):
116124
def __init__(self, module):
117125
super(ClouderaParcelInfo, self).__init__(module)
118-
self.cluster_name = self.get_param("cluster_name")
119-
self.product = self.get_param("product")
126+
127+
self.cluster = self.get_param("cluster")
128+
self.parcel = self.get_param("name")
120129
self.parcel_version = self.get_param("parcel_version")
130+
131+
self.output = {}
132+
self.changed = False
133+
121134
self.process()
122135

123136
@ClouderaManagerModule.handle_process
124137
def process(self):
125-
parcel_api_instance = ParcelResourceApi(self.api_client)
126-
parcels_api_instance = ParcelsResourceApi(self.api_client)
127-
cluster_api_instance = ClustersResourceApi(self.api_client)
128138

129-
self.parcel_output = {}
130-
self.changed = False
139+
parcel_api = ParcelResourceApi(self.api_client)
140+
parcels_api = ParcelsResourceApi(self.api_client)
141+
cluster_api = ClustersResourceApi(self.api_client)
131142

132143
try:
133-
cluster_api_instance.read_cluster(cluster_name=self.cluster_name).to_dict()
144+
cluster_api.read_cluster(cluster_name=self.cluster)
134145
except ApiException as ex:
135146
if ex.status == 404:
136-
self.module.fail_json(msg=f" Cluster {self.cluster_name} {ex.reason}")
137-
138-
if self.product and self.parcel_version:
139-
self.parcel_info = parcel_api_instance.read_parcel(
140-
cluster_name=self.cluster_name,
141-
product=self.product,
142-
version=self.parcel_version,
143-
).to_dict()
144-
self.parcel_output = {"items": [self.parcel_info]}
147+
self.module.fail_json(msg=f"Cluster '{self.cluster}' not found")
148+
149+
if self.parcel and self.parcel_version:
150+
try:
151+
parcel_info = parcel_api.read_parcel(
152+
cluster_name=self.cluster,
153+
product=self.parcel,
154+
version=self.parcel_version,
155+
)
156+
self.output = [parse_parcel_result(parcel_info)]
157+
except ApiException as ex:
158+
if ex.status == 404:
159+
pass
145160
else:
146-
self.parcel_output = parcels_api_instance.read_parcels(
147-
cluster_name=self.cluster_name
148-
).to_dict()
161+
self.output = [
162+
parse_parcel_result(p)
163+
for p in parcels_api.read_parcels(cluster_name=self.cluster).items
164+
]
149165

150166

151167
def main():
152168
module = ClouderaManagerModule.ansible_module(
153169
argument_spec=dict(
154-
cluster_name=dict(required=True, type="str"),
155-
product=dict(required=False, type="str"),
156-
parcel_version=dict(required=False, type="str"),
170+
cluster=dict(required=True, aliases=["cluster_name"]),
171+
name=dict(aliases=["product", "parcel"]),
172+
parcel_version=dict(),
157173
),
158174
supports_check_mode=True,
159175
required_together=[
160-
("product", "parcel_version"),
176+
("name", "parcel_version"),
161177
],
162178
)
163179

164180
result = ClouderaParcelInfo(module)
165181

166-
changed = result.changed
167-
168182
output = dict(
169-
changed=changed,
170-
cloudera_manager=result.parcel_output,
183+
changed=result.changed,
184+
parcels=result.output,
171185
)
172186

173187
if result.debug:

tests/unit/plugins/modules/parcel/test_parcel.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,18 @@ def conn():
5454
}
5555

5656

57+
def test_invalid_cluster(module_args, conn):
58+
conn.update(
59+
cluster_name="BOOM",
60+
parcel="test",
61+
parcel_version="test",
62+
)
63+
module_args(conn)
64+
65+
with pytest.raises(AnsibleFailJson, match="Cluster 'BOOM' not found"):
66+
parcel.main()
67+
68+
5769
def test_pytest_download_parcel(conn, module_args):
5870
conn.update(
5971
cluster_name=os.getenv("CM_CLUSTER"),

0 commit comments

Comments
 (0)