Skip to content

Commit 7616fe8

Browse files
authored
Add Datalake service lookup (#97)
* Refactor parsing to shared cdp_service class * Add datalake_service lookup plugin Signed-off-by: Webster Mudge <wmudge@cloudera.com>
1 parent 608ad11 commit 7616fe8

File tree

3 files changed

+165
-24
lines changed

3 files changed

+165
-24
lines changed

plugins/lookup/cdp_service.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Copyright 2023 Cloudera, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from ansible.errors import AnsibleError
16+
from ansible.plugins.lookup import LookupBase
17+
from ansible.module_utils.common.text.converters import to_text, to_native
18+
from ansible.utils.display import Display
19+
20+
display = Display()
21+
22+
class CdpServiceLookupModule(LookupBase):
23+
def parse_services(self, terms:list, name:str, entity:dict, service:str):
24+
lookup = 'knoxService' if self.get_option('knox_service') else 'serviceName'
25+
results = []
26+
try:
27+
for term in LookupBase._flatten(terms):
28+
display.vvv("%s_service lookup connecting to '%s[%s]'" % (service, name, term))
29+
services = [s for s in entity['endpoints']['endpoints'] if s[lookup] == term and 'serviceUrl' in s]
30+
if services:
31+
results.append([to_text(s['serviceUrl']) for s in services])
32+
else:
33+
results.append(self.get_option('default'))
34+
return results
35+
except KeyError as e:
36+
raise AnsibleError("Error parsing result for '%s':'" % (name, to_native(e)))

plugins/lookup/datahub_service.py

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -85,40 +85,24 @@
8585
'''
8686

8787
from ansible.errors import AnsibleError
88-
from ansible.module_utils.common.text.converters import to_text, to_native
89-
from ansible.plugins.lookup import LookupBase
90-
from ansible.utils.display import Display
88+
from ansible.module_utils.common.text.converters import to_native
9189

9290
from cdpy.cdpy import Cdpy
9391
from cdpy.common import CdpError
9492

95-
display = Display()
93+
from ansible_collections.cloudera.cloud.plugins.lookup.cdp_service import CdpServiceLookupModule
9694

97-
class LookupModule(LookupBase):
95+
96+
class LookupModule(CdpServiceLookupModule):
9897
def run(self, terms, variables=None, **kwargs):
9998
self.set_options(var_options=variables, direct=kwargs)
10099

101-
lookup = 'knoxService' if self.get_option('knox_service') else 'serviceName'
102-
103-
try:
104-
results = []
100+
try:
105101
datahub = Cdpy().datahub.describe_cluster(self.get_option('datahub'))
106-
102+
107103
if datahub is None:
108104
raise AnsibleError("No Datahub found for '%s'" % self.get_option('datahub'))
109-
110-
for term in LookupModule._flatten(terms):
111-
display.vvv("datahub_service lookup connecting to '%s[%s]'" % (self.get_option('datahub'), term))
112-
113-
services = [s for s in datahub['endpoints']['endpoints'] if s[lookup] == term and 'serviceUrl' in s]
114-
115-
if services:
116-
results.append([to_text(s['serviceUrl']) for s in services])
117-
else:
118-
results.append(self.get_option('default'))
119-
120-
return results
121-
except KeyError as e:
122-
raise AnsibleError("Error parsing Datahub result for '%s':'" % (self.get_option('datahub'), to_native(e)))
105+
106+
return self.parse_services(terms, self.get_option('datahub'), datahub, 'datahub')
123107
except CdpError as e:
124108
raise AnsibleError("Error connecting to service '%s': %s" % (self.get_option('datahub'), to_native(e)))

plugins/lookup/datalake_service.py

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# Copyright 2023 Cloudera, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from __future__ import (absolute_import, division, print_function)
16+
__metaclass__ = type
17+
18+
DOCUMENTATION = '''
19+
lookup: datalake_service
20+
author: Webster Mudge (@wmudge) <wmudge@cloudera.com>
21+
short_description: Get the URL for a CDP Public Cloud Datalake service
22+
description:
23+
- Allows you to retrieve the URL for a given CDP Public Cloud Datalake service.
24+
- If no service name (or optionally Knox service name) is found on the specified Datalake, the lookup returns the value of I(default).
25+
- Otherwise, the lookup entry will be an empty list.
26+
- If the Datalake is not found or is ambigious, the lookup will return an error.
27+
options:
28+
_terms:
29+
description:
30+
- An endpoint C(serviceName) or list of them to lookup within the Datalake.
31+
- If I(knox_service=True), then these values will lookup against the endpoint C(knoxService).
32+
required: True
33+
sample:
34+
- CM-API
35+
- CM-UI
36+
- ATLAS_SERVER
37+
- RANGER_ADMIN
38+
environment:
39+
description: Name of the Environment of the Datalake to query
40+
type: string
41+
datalake:
42+
description: Name of the Datalake to query
43+
type: string
44+
default:
45+
description: What return when the service name is not found on the Datahub
46+
type: raw
47+
default: []
48+
knox_service:
49+
description: Whether the terms are C(serviceName) or C(knoxService) values.
50+
type: boolean
51+
default: False
52+
notes:
53+
- You can pass the C(Undefined) object as C(default) to force an undefined error.
54+
- Requires C(cdpy).
55+
'''
56+
57+
EXAMPLES = '''
58+
- name: Retrieve the details for the Ranger Admin service, via Environment reference
59+
ansible.builtin.debug:
60+
msg: "{{ lookup('cloudera.cloud.datalake_service', 'RANGER_ADMIN', environment='example-env', wantlist=True) }}"
61+
62+
- name: Retrieve the details for the Ranger Admin service, via explicit Datalake reference
63+
ansible.builtin.debug:
64+
msg: "{{ lookup('cloudera.cloud.datalake_service', 'RANGER_ADMIN', datalake='example-dl', wantlist=True) }}"
65+
66+
- name: Return a generated list if the service does not exist
67+
ansible.builtin.debug:
68+
msg: "{{ query('cloudera.cloud.datalake_service', 'NO_SERVICE', environment='example-env', default=['something', 'else']) }}"
69+
70+
- name: Return multiple services from the same Datalake
71+
ansible.builtin.debug:
72+
msg: "{{ query('cloudera.cloud.datalake_service', 'RANGER_ADMIN', 'ATLAS_SERVER', 'CM-API', environment='example-env') }}"
73+
74+
- name: Return multiple services, specified as a list
75+
ansible.builtin.debug:
76+
msg: "{{ query('cloudera.cloud.datalake_service', ['RANGER_ADMIN', 'ATLAS_SERVER', 'CM-API'], environment='example-env') }}"
77+
78+
- name: Look up via Knox service
79+
ansible.builtin.debug:
80+
msg: "{{ query('cloudera.cloud.datalake_service', 'ATLAS_API', environment='example-env', knox_service=True) }}"
81+
'''
82+
83+
RETURN = '''
84+
_list:
85+
description: List of lists of service URLs
86+
type: list
87+
elements: list
88+
'''
89+
90+
from ansible.errors import AnsibleError
91+
from ansible.module_utils.common.text.converters import to_native
92+
93+
from cdpy.cdpy import Cdpy
94+
from cdpy.common import CdpError
95+
96+
from ansible_collections.cloudera.cloud.plugins.lookup.cdp_service import CdpServiceLookupModule
97+
98+
99+
class LookupModule(CdpServiceLookupModule):
100+
def run(self, terms, variables=None, **kwargs):
101+
self.set_options(var_options=variables, direct=kwargs)
102+
103+
if not self.get_option('datalake') and not self.get_option('environment'):
104+
raise AnsibleError("One of 'environment' or 'datalake' parameters must be present")
105+
106+
try:
107+
dl = None
108+
if self.get_option('datalake'):
109+
dl = Cdpy().datalake.describe_datalake(self.get_option('datalake'))
110+
if dl is None:
111+
raise AnsibleError("No Datalake found for '%s'" % self.get_option('datalake'))
112+
else:
113+
env = Cdpy().datalake.describe_all_datalakes(self.get_option('environment'))
114+
if not env:
115+
raise AnsibleError("No Environment found for '%s'" % self.get_option('environment'))
116+
elif len(env) > 1:
117+
raise AnsibleError("Multiple Datalakes found for Enviroment '%s'" % self.get_option('environment'))
118+
dl = env[0]
119+
return self.parse_services(terms, dl['datalakeName'], dl, 'datalake')
120+
except CdpError as e:
121+
raise AnsibleError("Error connecting to CDP: %s" % to_native(e))

0 commit comments

Comments
 (0)