-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcontainer_cluster.py
274 lines (239 loc) · 8.4 KB
/
container_cluster.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright 2022 Illumio, Inc. All Rights Reserved.
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = r'''
---
module: container_cluster
short_description: Create/update/delete Illumio PCE container clusters
description:
- This module allows you to create and manipulate container cluster objects on the Illumio PCE to sync with Kubernetes or OpenShift clusters.
- Only the name and description values for the cluster can be set when creating or updating a cluster.
All other values are computed based on the sync data from a Kubelink pod installed in the cluster.
- Supports check mode.
author:
- Duncan Sommerville (@dsommerville-illumio)
requirements:
- "python>=3.8"
- "illumio>=1.1.3"
version_added: "0.2.0"
options:
href:
description: HREF of an existing container cluster.
type: str
name:
description:
- Container cluster display name.
- Required for creating a container cluster or when C(href) is not specified.
type: str
description:
description: Container cluster description.
type: str
default: ''
state:
description:
- Desired container cluster state.
- If C(present), the cluster will be created if it does not exist, or updated to match the provided parameters if it does.
- If C(absent), the cluster will be removed if it exists.
type: str
choices: ['present', 'absent']
default: 'present'
extends_documentation_fragment:
- illumio.core.pce
'''
EXAMPLES = r'''
- name: "Create container cluster"
illumio.core.container_cluster:
name: CC-KUBE
description: Kubernetes cluster
state: present
register: container_cluster_result
- name: "Store container cluster token"
set_fact:
kube_cluster_token: "{{ container_cluster_result.container_cluster['container_cluster_token'] }}"
- name: "Remove existing cluster"
illumio.core.pairing_profile:
name: CC-KUBE
state: absent
- name: "Remove cluster by HREF"
illumio.core.pairing_profile:
href: /orgs/1/container_clusters/f5bef182-8c55-4219-b35b-0a50b707e434
state: absent
'''
RETURN = r'''
container_cluster:
description: Information about the container cluster that was created or updated.
type: complex
returned: success
contains:
href:
description: The container cluster's HREF.
type: str
returned: always
name:
description: The container cluster's name.
type: str
returned: always
description:
description: A description of the container cluster.
type: str
returned: always
pce_fqdn:
description: PCE fully-qualified domain name.
type: str
returned: always
manager_type:
description: Container cluster type and version.
type: str
returned: always
sample: Kubernetes v1.24.1
last_connected:
description: ISO date-timestamp of the last heartbeat from the container cluster to the PCE.
type: str
returned: always
sample: "2022-06-23T20:53:57.885Z"
kubelink_version:
description: Version of the Kubelink software used to pair this cluster to the PCE.
type: str
returned: always
sample: "2.0.2.d53d7f"
online:
description: Whether or not the container cluster is online.
type: bool
returned: always
nodes:
description: List of node names and pod subnets belonging to the cluster.
type: list
elements: dict
returned: always
sample:
- name: kube-leader
pod_subnet: "192.168.0.0/24"
container_runtime:
description: Default container runtime for the cluster.
type: str
returned: always
sample: containerd
errors:
description: List of errors to do with the container cluster.
type: list
elements: dict
returned: always
sample:
- audit_event:
href: /orgs/1/events/daa015a0-257a-4d43-874f-64039742c482
duplicate_ids: []
error_type: container_cluster.duplicate_machine_id
caps:
description:
- Array of permissions on the entity held by the requesting user.
- An empty array implies readonly permission.
type: list
elements: str
returned: always
container_cluster_token:
description:
- The pairing token for the cluster.
- This token is only returned once when the cluster is created.
- It cannot be retrieved through the API after this, so make sure to store it in a secure, persistent form.
type: str
returned: on successful creation
sample:
container_cluster:
href: /orgs/1/container_clusters/f5bef182-8c55-4219-b35b-0a50b707e434
pce_fqdn: null
name: CC-EKS-LAB
description: Lab Kubernetes cluster in AWS
manager_type: Kubernetes v1.24.1
last_connected: "2022-06-23T20:53:57.885Z"
kubelink_version: "2.0.2.d53d7f"
online: true
nodes:
- name: kube-leader
pod_subnet: "192.168.0.0/24"
container_runtime: containerd
errors: []
caps:
- write
container_cluster_token: "1_0dfec0acb8e4bc53e052874874da0c24e7ac98da3b3954e3c9ea6f9860722e84"
'''
import sys
import traceback
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
from ansible_collections.illumio.core.plugins.module_utils.pce import PceObjectApi, pce_connection_spec # type: ignore
IMPORT_ERROR_TRACEBACK = ''
try:
from illumio.infrastructure import ContainerCluster
except ImportError:
ContainerCluster = None
# replicate the traceback formatting from AnsibleModule.fail_json
IMPORT_ERROR_TRACEBACK = ''.join(traceback.format_tb(sys.exc_info()[2]))
class ContainerClusterApi(PceObjectApi):
def __init__(self, module: AnsibleModule) -> None:
super().__init__(module)
self._api = self._pce.container_clusters
def params_match(self, o):
return self._module.params.get('name') == getattr(o, 'name', None) \
and self._module.params.get('description') == getattr(o, 'description', None)
def spec():
return dict(
href=dict(type='str'),
name=dict(type='str'),
description=dict(type='str', default=''),
state=dict(
type='str',
choices=['present', 'absent'],
default='present'
)
)
def main():
argument_spec = pce_connection_spec()
argument_spec.update(spec())
module = AnsibleModule(
argument_spec=argument_spec,
required_one_of=[['name', 'href']],
supports_check_mode=True
)
if not ContainerCluster:
module.fail_json(
msg=missing_required_lib('illumio', url='https://pypi.org/project/illumio/'),
exception=IMPORT_ERROR_TRACEBACK
)
container_cluster_api = ContainerClusterApi(module)
href = module.params.get('href')
name = module.params.get('name')
description = module.params.get('description')
state = module.params.get('state')
if href:
existing_cluster = container_cluster_api.get_by_href(href)
if not existing_cluster:
module.fail_json("No container cluster found with HREF %s" % (href))
elif name:
existing_cluster = container_cluster_api.get_by_name(name)
if state == 'present':
new_cluster = ContainerCluster(
name=name,
description=description
)
if module.check_mode:
if not existing_cluster:
module.exit_json(changed=True, container_cluster=container_cluster_api.json_output(new_cluster))
module.exit_json(
changed=not container_cluster_api.params_match(existing_cluster),
container_cluster=container_cluster_api.json_output(new_cluster)
)
if not existing_cluster:
cluster = container_cluster_api.create(new_cluster)
changed = True
else:
changed = container_cluster_api.update(existing_cluster, new_cluster)
cluster = container_cluster_api.get_by_href(existing_cluster.href) if changed else existing_cluster
elif state == 'absent':
if module.check_mode:
module.exit_json(changed=True, container_cluster={})
changed = container_cluster_api.delete(existing_cluster)
cluster = {}
module.exit_json(changed=changed, container_cluster=container_cluster_api.json_output(cluster))
if __name__ == '__main__':
main()