Skip to content

Commit f64ce9b

Browse files
authored
Add ECS cluster functions (#251)
Signed-off-by: rsuplina <[email protected]>
1 parent cc30235 commit f64ce9b

File tree

2 files changed

+444
-32
lines changed

2 files changed

+444
-32
lines changed

plugins/modules/cluster.py

Lines changed: 202 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
import json
15+
import json, yaml
1616

1717
from ansible.module_utils.common.text.converters import to_text, to_native
1818

@@ -55,6 +55,8 @@
5555
ServicesResourceApi,
5656
RoleConfigGroupsResourceApi,
5757
RolesResourceApi,
58+
ControlPlanesResourceApi,
59+
ApiInstallEmbeddedControlPlaneArgs,
5860
)
5961
from cm_client.rest import ApiException
6062

@@ -348,6 +350,29 @@
348350
required: no
349351
aliases:
350352
- role_type
353+
control_plane:
354+
description:
355+
- Private Cloud Control Plane on embedded kubernetes
356+
type: dict
357+
required: no
358+
suboptions:
359+
remote_repo_url:
360+
description:
361+
- The url of the remote repository where the private cloud artifacts to install are hosted.
362+
type: str
363+
required: yes
364+
datalake_cluster_name:
365+
description:
366+
- The name of the datalake cluster to use for the initial environment in this control plane.
367+
type: str
368+
required: yes
369+
control_plane_config:
370+
description:
371+
- A yaml structured dictionary with configuration parameters for the installation.
372+
type: dict
373+
required: yes
374+
aliases:
375+
- values_yaml
351376
parcels:
352377
description:
353378
- The parcels by version enabled for a cluster.
@@ -629,10 +654,123 @@
629654
username: "jane_smith"
630655
password: "S&peR4Ec*re"
631656
port: 7180
632-
cluster_name: example-cluster
657+
cluster_name: ECS-cluster
633658
cluster_version: "1.5.1-b626.p0.42068229"
634659
cluster_type: EXPERIENCE_CLUSTER
635660
state: present
661+
parcels:
662+
ECS: "1.5.1-b626.p0.42068229"
663+
services:
664+
- name: docker
665+
type: DOCKER
666+
config:
667+
docker_images_destination_registry_user: registry-user
668+
defaultDataPath: /mnt/docker
669+
- name: ecs
670+
type: ECS
671+
config:
672+
app_domain: test.lab.example
673+
k8s_webui_secret_admin_token: ecs-k8s_webui_secret_admin_token
674+
cp_prometheus_ingress_user: cloudera-manager
675+
infra_prometheus_ingress_user: cloudera-manager
676+
longhorn_replication: 2
677+
lsoDataPath: /ecs/local
678+
docker: docker
679+
cp_prometheus_ingress_password: password1
680+
infra_prometheus_ingress_password: password1
681+
defaultDataPath: /ecs/longhorn-storage
682+
nfs_over_provisioning: 800
683+
host_templates:
684+
- name: ecs_master
685+
role_groups:
686+
- service_type: DOCKER
687+
type: DOCKER_SERVER
688+
- service_type: ECS
689+
type: ECS_SERVER
690+
- name: ecs_workers
691+
role_groups:
692+
- service_type: DOCKER
693+
type: DOCKER_SERVER
694+
- service_type: ECS
695+
type: ECS_AGENT
696+
hosts:
697+
- name: ecs-master-01.test.lab.example
698+
host_template: ecs_master
699+
- name: ecs-worker-01.test.lab.example
700+
host_template: ecs_workers
701+
- name: ecs-worker-02.test.lab.example
702+
host_template: ecs_workers
703+
- name: ecs-worker-03.test.lab.example
704+
host_template: ecs_workers
705+
control_plane:
706+
datalake_cluster_name: PVC-Base
707+
remote_repo_url: "https://test_website/cdp-pvc-ds/1.5.1"
708+
control_plane_config:
709+
ContainerInfo:
710+
Mode: public
711+
CopyDocker: false
712+
Database:
713+
Mode: embedded
714+
EmbeddedDbStorage: 50
715+
Services:
716+
thunderheadenvironment:
717+
Config:
718+
database:
719+
name: db-env
720+
mlxcontrolplaneapp:
721+
Config:
722+
database:
723+
name: db-mlx
724+
dwx:
725+
Config:
726+
database:
727+
name: db-dwx
728+
cpxliftie:
729+
Config:
730+
database:
731+
name: db-liftie
732+
dex:
733+
Config:
734+
database:
735+
name: db-dex
736+
resourcepoolmanager:
737+
Config:
738+
database:
739+
name: db-resourcepoolmanager
740+
cdpcadence:
741+
Config:
742+
database:
743+
name: db-cadence
744+
cdpcadencevisibility:
745+
Config:
746+
database:
747+
name: db-cadence-visibility
748+
clusteraccessmanager:
749+
Config:
750+
database:
751+
name: db-clusteraccessmanager
752+
monitoringapp:
753+
Config:
754+
database:
755+
name: db-alerts
756+
thunderheadusermanagementprivate:
757+
Config:
758+
database:
759+
name: db-ums
760+
classicclusters:
761+
Config:
762+
database:
763+
name: cm-registration
764+
clusterproxy:
765+
Config:
766+
database:
767+
name: cluster-proxy
768+
dssapp:
769+
Config:
770+
database:
771+
name: db-dss-app
772+
Vault:
773+
Mode: embedded
636774
"""
637775

638776
RETURN = r"""
@@ -698,6 +836,7 @@ def __init__(self, module):
698836
self.display_name = self.get_param("display_name")
699837
self.contexts = self.get_param("contexts")
700838
self.auto_assign = self.get_param("auto_assign")
839+
self.control_plane = self.get_param("control_plane")
701840

702841
self.changed = False
703842
self.output = {}
@@ -717,6 +856,7 @@ def process(self):
717856
self.host_api = HostsResourceApi(self.api_client)
718857
self.role_group_api = RoleConfigGroupsResourceApi(self.api_client)
719858
self.role_api = RolesResourceApi(self.api_client)
859+
self.control_plane_api = ControlPlanesResourceApi(self.api_client)
720860

721861
refresh = True
722862

@@ -991,15 +1131,16 @@ def create_cluster_from_parameters(self):
9911131
rcg["name"]
9921132
if rcg["name"]
9931133
else self.find_base_role_group_name(
994-
service_type=rcg["service"], role_type=rcg["type"]
1134+
service_name=rcg["service"],
1135+
service_type=rcg["service_type"],
1136+
role_type=rcg["type"],
9951137
)
9961138
)
9971139
for rcg in ht["role_groups"]
9981140
],
9991141
)
10001142
for ht in self.host_templates
10011143
]
1002-
10031144
self.host_template_api.create_host_templates(
10041145
cluster_name=self.name,
10051146
body=ApiHostTemplateList(items=templates),
@@ -1174,6 +1315,25 @@ def create_cluster_from_parameters(self):
11741315
msg="Role not found. No role type '%s' for service '%s' found on host '%s'"
11751316
% (override["type"], override["service"], hostref.hostname)
11761317
)
1318+
# Configure the experience cluster
1319+
if self.control_plane:
1320+
values_yaml_data = self.control_plane["control_plane_config"]
1321+
values_yaml_str = yaml.dump(values_yaml_data)
1322+
1323+
# Assemble body for Install Control Plane request
1324+
body = ApiInstallEmbeddedControlPlaneArgs(
1325+
experience_cluster_name=self.name,
1326+
containerized_cluster_name=self.name,
1327+
datalake_cluster_name=self.control_plane["datalake_cluster_name"],
1328+
remote_repo_url=self.control_plane["remote_repo_url"],
1329+
values_yaml=values_yaml_str,
1330+
)
1331+
setup_control_plane = (
1332+
self.control_plane_api.install_embedded_control_plane(body=body)
1333+
)
1334+
self.wait_for_command_state(
1335+
command_id=setup_control_plane.id, polling_interval=self.delay
1336+
)
11771337

11781338
# Execute auto-role assignments
11791339
if self.auto_assign:
@@ -1246,15 +1406,28 @@ def marshal_hostrefs(self, hosts: dict) -> list[ApiHostRef]:
12461406
)
12471407
return results
12481408

1249-
def find_base_role_group_name(self, service_type: str, role_type: str) -> str:
1250-
rcgs = [
1251-
rcg
1252-
for s in self.service_api.read_services(cluster_name=self.name).items
1253-
for rcg in self.role_group_api.read_role_config_groups(
1254-
cluster_name=self.name, service_name=s.name
1255-
).items
1256-
if s.type == service_type
1257-
]
1409+
def find_base_role_group_name(
1410+
self, role_type: str, service_name: str = None, service_type: str = None
1411+
) -> str:
1412+
if service_name:
1413+
1414+
rcgs = [
1415+
rcg
1416+
for s in self.service_api.read_services(cluster_name=self.name).items
1417+
for rcg in self.role_group_api.read_role_config_groups(
1418+
cluster_name=self.name, service_name=s.name
1419+
).items
1420+
if s.name == service_name
1421+
]
1422+
elif service_type:
1423+
rcgs = [
1424+
rcg
1425+
for s in self.service_api.read_services(cluster_name=self.name).items
1426+
for rcg in self.role_group_api.read_role_config_groups(
1427+
cluster_name=self.name, service_name=s.name
1428+
).items
1429+
if s.type == service_type
1430+
]
12581431

12591432
base = next(
12601433
iter([rcg for rcg in rcgs if rcg.base and rcg.role_type == role_type]),
@@ -1263,8 +1436,8 @@ def find_base_role_group_name(self, service_type: str, role_type: str) -> str:
12631436

12641437
if base is None:
12651438
self.module.fail_json(
1266-
"Invalid role group; unable to discover base role group for service role, %s[%s]"
1267-
% (role_type, service_type)
1439+
"Invalid role group; unable to discover base role group for service role, %s"
1440+
% role_type
12681441
)
12691442
else:
12701443
return base.name
@@ -1367,21 +1540,30 @@ def main():
13671540
required=True,
13681541
options=dict(
13691542
name=dict(aliases=["ref", "ref_name"]),
1370-
service=dict(
1371-
required=True, aliases=["service_name", "service_ref"]
1372-
),
1543+
service=dict(aliases=["service_name", "service_ref"]),
13731544
type=dict(aliases=["role_type"]),
1545+
service_type=dict(),
13741546
),
13751547
aliases=["role_config_groups"],
13761548
mutually_exclusive=[
1377-
("name", "type"),
1549+
("service", "service_type"),
13781550
],
13791551
requires_one_of=[
1380-
("name", "type"),
1552+
("service", "service_type"),
13811553
],
13821554
),
13831555
),
13841556
),
1557+
control_plane=dict(
1558+
type="dict",
1559+
options=dict(
1560+
remote_repo_url=dict(required=True, type="str"),
1561+
datalake_cluster_name=dict(required=True, type="str"),
1562+
control_plane_config=dict(
1563+
required=True, type="dict", aliases=["values_yaml"]
1564+
),
1565+
),
1566+
),
13851567
# Parcels is a dict of product:version of the cluster
13861568
parcels=dict(type="dict", aliases=["products"]),
13871569
# Tags is a dict of key:value assigned to the cluster

0 commit comments

Comments
 (0)