diff --git a/docsrc/index.rst b/docsrc/index.rst index cdac0aee..0065294d 100644 --- a/docsrc/index.rst +++ b/docsrc/index.rst @@ -19,6 +19,10 @@ cloudera.cloud Ansible Collection df_info dw_cluster dw_cluster_info + dw_database_catalog + dw_database_catalog_info + dw_virtual_warehouse + dw_virtual_warehouse_info env env_auth env_auth_info diff --git a/plugins/README.md b/plugins/README.md index 56867418..09e8ab8a 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -20,6 +20,10 @@ modules employ the underlying SDK contained within the `cdpy` Python package. | [df_info](./modules/df_info.py) | Gather information about CDP DataFlow services | | [dw_cluster](./modules/dw_cluster.py) | Create, manage, and destroy CDP Data Warehouse experiences | | [dw_cluster_info](./modules/dw_cluster_info.py) | Gather information about CDP Data Warehouse experiences | +| [dw_database_catalog](./modules/dw_database_catalog.py) | Create, manage, and destroy CDP Data Warehouse Data Catalogs | +| [dw_database_catalog_info](./modules/dw_database_catalog_info.py) | Gather information about CDP Data Warehouse Data Catalogs | +| [dw_virtual_warehouse](./modules/dw_virtual_warehouse.py) | Create, manage, and destroy CDP Data Warehouse Virtual Warehouses | +| [dw_virtual_warehouse_info](./modules/dw_virtual_warehouse_info.py) | Gather information about CDP Data Warehouse Virtual Warehouses | | [env](./modules/env.py) | Create, manage, and destroy CDP Environments | | [env_auth](./modules/env_auth.py) | Set authentication details for CDP Environments | | [env_auth_info](./modules/env_auth_info.py) | Gather information about CDP Environment authentication details | diff --git a/plugins/module_utils/cdp_common.py b/plugins/module_utils/cdp_common.py index 18e1205d..b1d43a2a 100644 --- a/plugins/module_utils/cdp_common.py +++ b/plugins/module_utils/cdp_common.py @@ -41,7 +41,7 @@ def process_debug(cls, f): def _impl(self, *args, **kwargs): result = f(self, *args, **kwargs) if self.debug: - self.log_out = self.cdpy.get_log() + self.log_out = self.cdpy.sdk.get_log() self.log_lines.append(self.log_out.splitlines()) return result @@ -73,11 +73,12 @@ def _get_param(self, param, default=None): def _cdp_module_throw_error(self, error: 'CdpError'): """Error handler for CDPy SDK""" - self.module.fail_json(msg=str(error.message), error=str(error.__dict__)) + self.module.fail_json(msg=str(error.message), error=str(error.__dict__), violations=error.violations) def _cdp_module_throw_warning(self, warning: 'CdpWarning'): """Warning handler for CDPy SDK""" - self.module.warn(warning.message) + if self.module._debug or self.module._verbosity >= 2: + self.module.warn(warning.message) @staticmethod def argument_spec(**spec): diff --git a/plugins/modules/dw_cluster.py b/plugins/modules/dw_cluster.py index 2fa5f2ed..df0b56b6 100644 --- a/plugins/modules/dw_cluster.py +++ b/plugins/modules/dw_cluster.py @@ -30,43 +30,63 @@ - Create or Delete CDP Data Warehouse Clusters author: - "Dan Chaffelson (@chaffelson)" + - "Saravanan Raju (@raju-saravanan)" + - "Webster Mudge (@wmudge)" requirements: - cdpy options: - id: + cluster_id: description: - - If an ID is provided, that Data Warehouse Cluster will be deleted if C(state=absent) + - The identifier of the Data Warehouse Cluster. + - Required if I(state=absent) and I(env) is not specified. type: str - required: When state is absent aliases: + - id - name env: - description: The name of the target environment + description: + - The name of the target environment. + - Required if I(state=present). + - Required if I(state=absent) and I(cluster_id) is not specified. type: str - required: when state is present aliases: - environment - env_crn + overlay: + description: + - Flag to use private IP addresses for Pods within the cluster. + - Otherwise, use IP addresses within the VPC. + type: bool + default: False + private_load_balancer: + description: Flag to set up a load balancer for private subnets. + type: bool + default: False aws_public_subnets: - description: List of zero or more Public AWS Subnet IDs to deploy to + description: + - List of zero or more Public AWS Subnet IDs used for deployment. + - Required if I(state=present) and the I(env) is deployed to AWS. type: list - required: when state is present for AWS deployment + elements: str aws_private_subnets: - description: List of zero or more Private AWS Subnet IDs to deploy to + description: + - List of zero or more Private AWS Subnet IDs used for deployment. + - Required if I(state=present) and the I(env) is deployed to AWS. type: list - required: when state is present for AWS deployment + elements: str az_subnet: - description: Azure Subnet Name, not URI + description: + - The Azure Subnet Name. + - Required if I(state=present) and the I(env) is deployed to Azure. type: str - required: when state is present for Azure deploymnet az_enable_az: - description: Whether to enable AZ mode or not + description: + - Flag to enable Availability Zone mode. + - Required if I(state=present) and the I(env) is deployed to Azure. type: bool - required: when state is present for Azure deployment state: - description: The declarative state of the Data Warehouse Cluster + description: The state of the Data Warehouse Cluster type: str - required: False default: present choices: - present @@ -76,14 +96,18 @@ - Flag to enable internal polling to wait for the Data Warehouse Cluster to achieve the declared state. - If set to FALSE, the module will return immediately. type: bool - required: False default: True + force: + description: + - Flag to enable force deletion of the Data Warehouse Cluster. + - This will not destroy the underlying cloud provider assets. + type: bool + default: False delay: description: - The internal polling interval (in seconds) while the module waits for the Data Warehouse Cluster to achieve the declared state. type: int - required: False default: 15 aliases: - polling_delay @@ -92,7 +116,6 @@ - The internal polling timeout (in seconds) while the module waits for the Data Warehouse Cluster to achieve the declared state. type: int - required: False default: 3600 aliases: - polling_timeout @@ -104,11 +127,6 @@ EXAMPLES = r''' # Note: These examples do not set authentication details. -# Delete a Data Warehouse Cluster -- cloudera.cloud.dw_cluster: - state: absent - id: my-id - # Request Azure Cluster creation - cloudera.cloud.dw_cluster: env_crn: crn:cdp:environments... @@ -120,60 +138,69 @@ env_crn: crn:cdp:environments... aws_public_subnets: [subnet-id-1, subnet-id-2] aws_private_subnets: [subnet-id-3, subnet-id-4] + +# Delete a Data Warehouse Cluster +- cloudera.cloud.dw_cluster: + state: absent + cluster_id: my-id + +# Delete the Data Warehouse Cluster within the Environment +- cloudera.cloud.dw_cluster: + state: absent + env: crn:cdp:environments... ''' RETURN = r''' --- -clusters: - description: The information about the named Cluster or Clusters - type: list - returned: always - elements: complex +cluster: + description: Details for the Data Warehouse cluster + type: dict contains: - cluster: - tyoe: dict + id: + description: The cluster identifier. + returned: always + type: str + environmentCrn: + description: The CRN of the cluster's Environment + returned: always + type: str + crn: + description: The cluster's CRN. + returned: always + type: str + creationDate: + description: The creation timestamp of the cluster in UTC. + returned: always + type: str + status: + description: The status of the cluster + returned: always + type: str + creator: + description: The cluster creator details. + returned: always + type: dict contains: - name: - description: The name of the cluster. - returned: always - type: str - environmentCrn: - description: The crn of the cluster's environment. - returned: always - type: str crn: - description: The cluster's crn. - returned: always + description: The Actor CRN. type: str - creationDate: - description: The creation time of the cluster in UTC. returned: always + email: + description: Email address (users). type: str - status: - description: The status of the Cluster - returned: always + returned: when supported + workloadUsername: + description: Username (users). type: str - creator: - description: The CRN of the cluster creator. - returned: always - type: dict - contains: - crn: - type: str - description: Actor CRN - email: - type: str - description: Email address for users - workloadUsername: - type: str - description: Username for users - machineUsername: - type: str - description: Username for machine users - cloudPlatform: - description: The cloud platform of the environment that was used to create this cluster - returned: always + returned: when supported + machineUsername: + description: Username (machine users). type: str + returned: when supported + cloudPlatform: + description: The cloud platform of the environment that was used to create this cluster. + returned: always + type: str sdk_out: description: Returns the captured CDP SDK log. returned: when supported @@ -194,6 +221,7 @@ def __init__(self, module): self.name = self._get_param('name') self.env = self._get_param('env') self.overlay = self._get_param('overlay') + self.private_load_balancer = self._get_param('private_load_balancer') self.az_subnet = self._get_param('az_subnet') self.az_enable_az = self._get_param('az_enable_az') self.aws_public_subnets = self._get_param('aws_public_subnets') @@ -205,7 +233,8 @@ def __init__(self, module): self.timeout = self._get_param('timeout') # Initialize return values - self.clusters = [] + self.cluster = {} + self.changed = False # Initialize internal values self.target = None @@ -216,6 +245,7 @@ def __init__(self, module): @CdpModule._Decorators.process_debug def process(self): env_crn = self.cdpy.environments.resolve_environment_crn(self.env) + # Check if Cluster exists if self.name is not None: self.target = self.cdpy.dw.describe_cluster(cluster_id=self.name) @@ -227,22 +257,23 @@ def process(self): elif len(listing) == 0: self.target = None else: - self.module.fail_json( - msg="Got ambiguous listing result for DW Clusters in Environment %s" % self.env) + self.module.fail_json(msg="Received multiple (i.e. ambiguous) Clusters in Environment %s" % self.env) else: self.target = None + if self.target is not None: - # Cluster Exists + # Begin Cluster Exists if self.state == 'absent': # Begin Delete if self.module.check_mode: - self.clusters.append(self.target) + self.cluster = self.target else: + self.changed = True if self.target['status'] not in self.cdpy.sdk.REMOVABLE_STATES: - self.module.warn( - "DW Cluster not in valid state for Delete operation: %s" % self.target['status']) + self.module.warn("Cluster is not in a valid state for Delete operations: %s" % self.target['status']) else: _ = self.cdpy.dw.delete_cluster(cluster_id=self.name, force=self.force) + if self.wait: self.cdpy.sdk.wait_for_state( describe_func=self.cdpy.dw.describe_cluster, @@ -250,80 +281,83 @@ def process(self): field=None, delay=self.delay, timeout=self.timeout ) else: - self.cdpy.sdk.sleep(3) # Wait for consistency sync - self.target = self.cdpy.dw.describe_cluster(cluster_id=self.name) - self.clusters.append(self.target) - # Drop Done + self.cdpy.sdk.sleep(self.delay) # Wait for consistency sync + self.cluster = self.cdpy.dw.describe_cluster(cluster_id=self.name) + # End Delete elif self.state == 'present': - # Being Config check - self.module.warn("DW Cluster already present and config validation is not implemented") + # Begin Config Check + self.module.warn("Cluster is already present and reconciliation is not yet implemented") if self.wait: self.target = self.cdpy.sdk.wait_for_state( describe_func=self.cdpy.dw.describe_cluster, params=dict(cluster_id=self.name), state='Running', delay=self.delay, timeout=self.timeout ) - self.clusters.append(self.target) - # End Config check + self.cluster = self.target + # End Config Check else: self.module.fail_json(msg="State %s is not valid for this module" % self.state) - # End handling Cluster exists + # End Cluster Exists else: - # Begin handling Cluster not found + # Begin Cluster Not Found if self.state == 'absent': - self.module.warn("DW CLuster %s already absent in Environment %s" % (self.name, self.env)) + self.module.warn("Cluster %s already absent in Environment %s" % (self.name, self.env)) elif self.state == 'present': - if self.module.check_mode: - pass - else: - # Being handle Cluster Creation + if not self.module.check_mode: + # Begin Cluster Creation + self.changed = True if env_crn is None: self.module.fail_json(msg="Could not retrieve CRN for CDP Environment %s" % self.env) else: self.name = self.cdpy.dw.create_cluster( - env_crn=env_crn, overlay=self.overlay, aws_public_subnets=self.aws_public_subnets, - aws_private_subnets=self.aws_private_subnets, az_subnet=self.az_subnet, - az_enable_az=self.az_enable_az + env_crn=env_crn, overlay=self.overlay, private_load_balancer=self.private_load_balancer, + aws_public_subnets=self.aws_public_subnets, aws_private_subnets=self.aws_private_subnets, + az_subnet=self.az_subnet, az_enable_az=self.az_enable_az ) if self.wait: - self.target = self.cdpy.sdk.wait_for_state( + self.cluster = self.cdpy.sdk.wait_for_state( describe_func=self.cdpy.dw.describe_cluster, params=dict(cluster_id=self.name), state='Running', delay=self.delay, timeout=self.timeout ) else: - self.target = self.cdpy.dw.describe_cluster(cluster_id=self.name) - self.clusters.append(self.target) + self.cluster = self.cdpy.dw.describe_cluster(cluster_id=self.name) + # End Cluster Creation else: - self.module.fail_json(msg="State %s is not valid for this module" % self.state) + self.module.fail_json(msg="Invalid state: %s" % self.state) + # End Cluster Not Found def main(): module = AnsibleModule( argument_spec=CdpModule.argument_spec( - name=dict(required=False, type='str', aliases=['id']), - env=dict(required=False, type='str', aliases=['environment', 'env_crn']), - overlay=dict(required=False, type='bool', default=False), - az_subnet=dict(required=False, type='str', default=None), - az_enable_az=dict(required=False, type='bool', default=None), - aws_public_subnets=dict(required=False, type='list', default=None), - aws_private_subnets=dict(required=False, type='list', default=None), - state=dict(required=False, type='str', choices=['present', 'absent'], default='present'), - force=dict(required=False, type='bool', default=False), - wait=dict(required=False, type='bool', default=True), - delay=dict(required=False, type='int', aliases=['polling_delay'], default=15), - timeout=dict(required=False, type='int', aliases=['polling_timeout'], default=3600) + cluster_id=dict(type='str', aliases=['id', 'name']), + env=dict(type='str', aliases=['environment', 'env_crn']), + overlay=dict(type='bool', default=False), + private_load_balancer=dict(type='bool', default=False), + az_subnet=dict(type='str'), + az_enable_az=dict(type='bool'), + aws_public_subnets=dict(type='list'), + aws_private_subnets=dict(type='list'), + state=dict(type='str', choices=['present', 'absent'], default='present'), + force=dict(type='bool', default=False), + wait=dict(type='bool', default=True), + delay=dict(type='int', aliases=['polling_delay'], default=15), + timeout=dict(type='int', aliases=['polling_timeout'], default=3600) ), required_together=[ ['az_subnet', 'az_enable_az'], ['aws_public_subnets', 'aws_private_subnets'] ], - required_one_of=[['name', 'env'], ], + required_if=[ + ['state', 'absent', ['cluster_id', 'env'], True], + ['state', 'present', ['env']] + ], supports_check_mode=True ) result = DwCluster(module) - output = dict(changed=False, clusters=result.clusters) + output = dict(changed=result.changed, cluster=result.cluster) if result.debug: output.update(sdk_out=result.log_out, sdk_out_lines=result.log_lines) diff --git a/plugins/modules/dw_cluster_info.py b/plugins/modules/dw_cluster_info.py index a9c0fab9..7892b727 100644 --- a/plugins/modules/dw_cluster_info.py +++ b/plugins/modules/dw_cluster_info.py @@ -34,20 +34,18 @@ requirements: - cdpy options: - id: + cluster_id: description: - - If a name is provided, that Data Warehouse Cluster will be described. - - environment must be provided if using name to retrieve a Cluster + - The identifier of the Data Warehouse Cluster. + - Mutually exclusive with I(environment). type: str - required: False aliases: - - name + - id environment: description: - - The name of the Environment in which to find and describe the Data Warehouse Clusters. - - Required with name to retrieve a Cluster + - The name or CRN of the Environment in which to find and describe Data Warehouse Clusters. + - Mutually exclusive with I(cluster_id). type: str - required: False aliases: - env extends_documentation_fragment: @@ -58,67 +56,71 @@ EXAMPLES = r''' # Note: These examples do not set authentication details. -# List basic information about all Data Warehouse Clusters +# List information about all Data Warehouse Clusters - cloudera.cloud.dw_cluster_info: -# Gather detailed information about a named Cluster +# Gather information about all Data Warehouse Clusters within an Environment - cloudera.cloud.dw_cluster_info: - name: example-cluster env: example-environment + +# Gather information about an identified Cluster +- cloudera.cloud.dw_cluster_info: + cluster_id: env-xyzabc ''' RETURN = r''' --- clusters: description: The information about the named Cluster or Clusters - type: list returned: always - elements: complex + type: list + elements: dict contains: - cluster: + id: + description: The cluster identifier. + returned: always + type: str + environmentCrn: + description: The CRN of the cluster's Environment + returned: always + type: str + crn: + description: The cluster's CRN. + returned: always + type: str + creationDate: + description: The creation timestamp of the cluster in UTC. + returned: always + type: str + status: + description: The status of the cluster + returned: always + type: str + creator: + description: The cluster creator details. + returned: always type: dict contains: - name: - description: The name of the cluster. - returned: always - type: str - environmentCrn: - description: The crn of the cluster's environment. - returned: always - type: str crn: - description: The cluster's crn. - returned: always + description: The Actor CRN. type: str - creationDate: - description: The creation time of the cluster in UTC. returned: always + email: + description: Email address (users). type: str - status: - description: The status of the Cluster - returned: always + returned: when supported + workloadUsername: + description: Username (users). type: str - creator: - description: The CRN of the cluster creator. - returned: always - type: dict - contains: - crn: - type: str - description: Actor CRN - email: - type: str - description: Email address for users - workloadUsername: - type: str - description: Username for users - machineUsername: - type: str - description: Username for machine users - cloudPlatform: - description: The cloud platform of the environment that was used to create this cluster - returned: always + returned: when supported + machineUsername: + description: Username (machine users). type: str + returned: when supported + cloudPlatform: + description: The cloud platform of the environment that was used to create this cluster. + returned: always + type: str sdk_out: description: Returns the captured CDP SDK log. returned: when supported @@ -136,8 +138,8 @@ def __init__(self, module): super(DwClusterInfo, self).__init__(module) # Set variables - self.id = self._get_param('name') - self.env = self._get_param('env') + self.cluster_id = self._get_param('cluster_id') + self.environment = self._get_param('environment') # Initialize return values self.clusters = [] @@ -147,24 +149,27 @@ def __init__(self, module): @CdpModule._Decorators.process_debug def process(self): - if self.id is not None: - cluster_single = self.cdpy.dw.describe_cluster(name=self.id) + if self.cluster_id is not None: + cluster_single = self.cdpy.dw.describe_cluster(self.cluster_id) if cluster_single is not None: self.clusters.append(cluster_single) - if self.env is not None: - env_crn = self.cdpy.environments.resolve_environment_crn(self.env) - if env_crn is not None: - self.clusters = self.cdpy.dw.gather_clusters(env_crn) + elif self.environment is not None: + env_crn = self.cdpy.environments.resolve_environment_crn(self.environment) + if env_crn: + self.clusters = self.cdpy.dw.list_clusters(env_crn=env_crn) else: - self.clusters = self.cdpy.dw.gather_clusters() + self.clusters = self.cdpy.dw.list_clusters() def main(): module = AnsibleModule( argument_spec=CdpModule.argument_spec( - id=dict(required=False, type='str', aliases=['name']), - env=dict(required=False, type='str', aliases=['environment']) + cluster_id=dict(type='str', aliases=['id']), + environment=dict(type='str', aliases=['env']) ), + mutually_exclusive=[ + ['cluster_id', 'environment'] + ], supports_check_mode=True ) diff --git a/plugins/modules/dw_database_catalog.py b/plugins/modules/dw_database_catalog.py new file mode 100644 index 00000000..168d654a --- /dev/null +++ b/plugins/modules/dw_database_catalog.py @@ -0,0 +1,254 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright 2021 Cloudera, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cloudera.cloud.plugins.module_utils.cdp_common import CdpModule + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community'} + +DOCUMENTATION = r''' +--- +module: dw_database_catalog +short_description: Create, manage, and destroy CDP Data Warehouse Database Catalogs +description: + - Create, manage, and destroy CDP Data Warehouse Database Catalogs +author: + - "Webster Mudge (@wmudge)" + - "Dan Chaffelson (@chaffelson)" + - "Saravanan Raju (@raju-saravanan)" +requirements: + - cdpy +options: + catalog_id: + description: + - The identifier of the Database Catalog. + - Required if C(state=absent). + type: str + aliases: + - id + cluster_id: + description: + - The identifier of the parent DW Cluster of the Database Catalog. + type: str + required: True + name: + description: + - The name of the Database Catalog. + - Required if C(state=present). + type: str + load_demo_data: + description: + - Flag to load demonstration data into the Database Catalog during creation. + type: str + wait: + description: + - Flag to enable internal polling to wait for the Data Catalog to achieve the declared state. + - If set to FALSE, the module will return immediately. + type: bool + default: True + delay: + description: + - The internal polling interval (in seconds) while the module waits for the Data Catalog to achieve the declared + state. + type: int + default: 15 + aliases: + - polling_delay + timeout: + description: + - The internal polling timeout (in seconds) while the module waits for the Data Catalog to achieve the declared + state. + type: int + default: 3600 + aliases: + - polling_timeout +extends_documentation_fragment: + - cloudera.cloud.cdp_sdk_options + - cloudera.cloud.cdp_auth_options +''' + +EXAMPLES = r''' +# Note: These examples do not set authentication details. + +# Create Database Catalog +- cloudera.cloud.dw_database_catalog: + name: example-database-catalog-name + cluster_id: example-cluster-id + +# Delete Database Catalog +- cloudera.cloud.dw_database_catalog: + catalog_id: example-database-id + cluster_id: example-cluster-id + state: absent +''' + +RETURN = r''' +--- +database_catalog: + description: Details about the Database Catalog. + returned: always + type: dict + contains: + id: + description: The identifier of the Database Catalog. + returned: always + type: str + name: + description: The name of the Database Catalog. + returned: always + type: str + status: + description: The status of the Database Catalog. + returned: always + type: str +sdk_out: + description: Returns the captured CDP SDK log. + returned: when supported + type: str +sdk_out_lines: + description: Returns a list of each line of the captured CDP SDK log. + returned: when supported + type: list + elements: str +''' + + +class DwDatabaseCatalog(CdpModule): + def __init__(self, module): + super(DwDatabaseCatalog, self).__init__(module) + + # Set variables + self.catalog_id = self._get_param('catalog_id') + self.cluster_id = self._get_param('cluster_id') + self.name = self._get_param('name') + self.load_demo_data = self._get_param('load_demo_data') + self.state = self._get_param('state') + self.wait = self._get_param('wait') + self.delay = self._get_param('delay') + self.timeout = self._get_param('timeout') + + # Initialize return values + self.database_catalog = {} + self.changed = False + + # Initialize internal values + self.target = None + + # Execute logic process + self.process() + + @CdpModule._Decorators.process_debug + def process(self): + if self.catalog_id is None: + dbcs = self.cdpy.dw.list_dbcs(cluster_id=self.cluster_id) + for dbc in dbcs: + if dbc['name'] == self.name: + self.target = self.cdpy.dw.describe_dbc(cluster_id=self.cluster_id, dbc_id=dbc['id']) + else: + self.target = self.cdpy.dw.describe_dbc(cluster_id=self.cluster_id, dbc_id=self.catalog_id) + + if self.target is not None: + # Begin Database Catalog Exists + if self.state == 'absent': + if self.module.check_mode: + self.database_catalog = self.target + else: + # Begin Drop + if self.target['status'] not in self.cdpy.sdk.REMOVABLE_STATES: + self.module.fail_json(msg= + "Database Catalog is not in a valid state for Delete operations: %s" % self.target['status']) + else: + _ = self.cdpy.dw.delete_dbc(cluster_id=self.cluster_id, dbc_id=self.target['id']) + self.changed = True + if self.wait: + self.cdpy.sdk.wait_for_state( + describe_func=self.cdpy.dw.describe_dbc, + params=dict(cluster_id=self.cluster_id, dbc_id=self.target['id']), + field=None, delay=self.delay, timeout=self.timeout + ) + else: + self.cdpy.sdk.sleep(self.delay) # Wait for consistency sync + self.database_catalog = self.cdpy.dw.describe_dbc(cluster_id=self.cluster_id, dbc_id=self.target['id']) + # End Drop + elif self.state == 'present': + # Begin Config Check + self.module.warn("Database Catalog already present and reconciliation is not yet implemented") + if self.wait: + self.target = self.cdpy.sdk.wait_for_state( + describe_func=self.cdpy.dw.describe_dbc, + params=dict(cluster_id=self.cluster_id, dbc_id=self.target['id']), + state=self.cdpy.sdk.STARTED_STATES, delay=self.delay, timeout=self.timeout + ) + self.database_catalog = self.target + # End Config Check + else: + self.module.fail_json(msg="Invalid state %s" % self.state) + # End Database Catalog Exists + else: + # Begin Database Catalog Not Found + if self.state == 'absent': + self.module.warn("Database Catalog %s already absent in Cluster %s" % (self.name, self.cluster_id)) + elif self.state == 'present': + if not self.module.check_mode: + dbc_id = self.cdpy.dw.create_dbc(cluster_id=self.cluster_id, name=self.name, + load_demo_data=self.load_demo_data) + self.changed = True + if self.wait: + self.database_catalog = self.cdpy.sdk.wait_for_state( + describe_func=self.cdpy.dw.describe_dbc, + params=dict(cluster_id=self.cluster_id, dbc_id=dbc_id), + state=self.cdpy.sdk.STARTED_STATES, delay=self.delay, timeout=self.timeout + ) + else: + self.database_catalog = self.cdpy.dw.describe_dbc(cluster_id=self.cluster_id, dbc_id=dbc_id) + else: + self.module.fail_json(msg="State %s is not valid for this module" % self.state) + # End Database Catalog Not Found + +def main(): + module = AnsibleModule( + argument_spec=CdpModule.argument_spec( + catalog_id=dict(type='str', aliases=['catalog_id']), + cluster_id=dict(required=True, type='str'), + name = dict(type='str'), + load_demo_data=dict(type='bool'), + state=dict(type='str', choices=['present', 'absent'], default='present'), + wait = dict(type='bool', default=True), + delay = dict(type='int', aliases=['polling_delay'], default=15), + timeout = dict(type='int', aliases=['polling_timeout'], default=3600) + ), + required_if=[ + ['state', 'present', ['name']], + ['state', 'absent', ['name', 'id'], True], + ], + mutually_exclusive=[['name', 'id']], + supports_check_mode=True + ) + + result = DwDatabaseCatalog(module) + output = dict(changed=result.changed, database_catalog=result.database_catalog) + + if result.debug: + output.update(sdk_out=result.log_out, sdk_out_lines=result.log_lines) + + module.exit_json(**output) + + +if __name__ == '__main__': + main() diff --git a/plugins/modules/dw_database_catalog_info.py b/plugins/modules/dw_database_catalog_info.py new file mode 100644 index 00000000..17ec07d6 --- /dev/null +++ b/plugins/modules/dw_database_catalog_info.py @@ -0,0 +1,159 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright 2021 Cloudera, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cloudera.cloud.plugins.module_utils.cdp_common import CdpModule + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community'} + +DOCUMENTATION = r''' +--- +module: dw_database_catalog_info +short_description: Gather information about CDP Data Warehouse Database Catalogs +description: + - Gather information about CDP Data Warehouse Database Catalogs +author: + - "Webster Mudge (@wmudge)" + - "Dan Chaffelson (@chaffelson)" + - "Saravanan Raju (@raju-saravanan)" +requirements: + - cdpy +options: + catalog_id: + description: + - The identifier of the Database Catalog. + - If undefined, will return a list of all Database Catalogs in the Cluster. + - Exclusive with I(name). + type: str + aliases: + - id + cluster_id: + description: + - The identifier of the parent Cluster of the Database Catalog or Catalogs. + type: str + required: True + name: + description: + - The name of the Database Catalog. + - If undefined, will return a list of all Database Catalogs in the Cluster. + - Exclusive with I(id). + type: str +extends_documentation_fragment: + - cloudera.cloud.cdp_sdk_options + - cloudera.cloud.cdp_auth_options +''' + +EXAMPLES = r''' +# Note: These examples do not set authentication details. + +# Get a single Database Catalog +- cloudera.cloud.dw_database_catalog_info: + name: example-database-catalog-name + cluster_id: example-cluster-id + +# Get all Database Catalogs within a Cluster +- cloudera.cloud.dw_database_catalog_info: + cluster_id: example-cluster-id +''' + +RETURN = r''' +--- +database_catalogs: + description: Details about the Database Catalogs. + returned: always + type: list + elements: dict + contains: + id: + description: The identifier of the Database Catalog. + returned: always + type: str + name: + description: The name of the Database Catalog. + returned: always + type: str + status: + description: The status of the Database Catalog. + returned: always + type: str +sdk_out: + description: Returns the captured CDP SDK log. + returned: when supported + type: str +sdk_out_lines: + description: Returns a list of each line of the captured CDP SDK log. + returned: when supported + type: list + elements: str +''' + + +class DwDatabaseCatalogInfo(CdpModule): + def __init__(self, module): + super(DwDatabaseCatalogInfo, self).__init__(module) + + # Set variables + self.catalog_id = self._get_param('catalog_id') + self.cluster_id = self._get_param('cluster_id') + self.name = self._get_param('name') + + # Initialize return values + self.database_catalogs = [] + + # Execute logic process + self.process() + + @CdpModule._Decorators.process_debug + def process(self): + if self.catalog_id is not None: + target = self.cdpy.dw.describe_dbc(cluster_id=self.cluster_id, dbc_id=self.catalog_id) + if target is not None: + self.database_catalogs.append(target) + else: + dbcs = self.cdpy.dw.list_dbcs(cluster_id=self.cluster_id) + if self.name is not None: + for dbc in dbcs: + if dbc['name'] == self.name: + self.database_catalogs.append(self.cdpy.dw.describe_dbc(cluster_id=self.cluster_id, dbc_id=dbc['id'])) + else: + self.database_catalogs = dbcs + + +def main(): + module = AnsibleModule( + argument_spec=CdpModule.argument_spec( + catalog_id=dict(type='str', aliases=['id']), + cluster_id=dict(required=True, type='str'), + name = dict(type='str'), + ), + mutually_exclusive=[['id', 'name']], + supports_check_mode=True + ) + + result = DwDatabaseCatalogInfo(module) + output = dict(changed=False, database_catalogs=result.database_catalogs) + + if result.debug: + output.update(sdk_out=result.log_out, sdk_out_lines=result.log_lines) + + module.exit_json(**output) + + +if __name__ == '__main__': + main() diff --git a/plugins/modules/dw_virtual_warehouse.py b/plugins/modules/dw_virtual_warehouse.py new file mode 100644 index 00000000..02b4deeb --- /dev/null +++ b/plugins/modules/dw_virtual_warehouse.py @@ -0,0 +1,473 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright 2021 Cloudera, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cloudera.cloud.plugins.module_utils.cdp_common import CdpModule + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community'} + +DOCUMENTATION = r''' +--- +module: dw_virtual_warehouse +short_description: Create, manage, and destroy CDP Data Warehouse Virtual Warehouses +description: + - Create CDP Virtual Warehouse +author: + - "Webster Mudge (@wmudge)" + - "Dan Chaffelson (@chaffelson)" + - "Saravanan Raju (@raju-saravanan)" +requirements: + - cdpy +options: + warehouse_id: + description: + - The identifier of the Virtual Warehouse. + - Required if C(state=absent). + type: str + aliases: + - vw_id + - id + cluster_id: + description: + - The identifier of the parent Data Warehouse Cluster of the Virtual Warehouse. + type: str + required: True + catalog_id: + description: + - The identifier of the parent Database Catalog attached to the Virtual Warehouse. + - Required if C(state=present) + type: str + aliases: + - dbc_id + type: + description: + - The type of Virtual Warehouse to be created. + - Required if C(state=present) + type: str + choices: + - hive + - impala + name: + description: + - The name of the Virtual Warehouse. + - Required if C(state=present) + type: str + template: + description: The name of deployment template for the Virtual Warehouse + type: str + choices: + - xsmall + - small + - medium + - large + autoscaling_min_nodes: + description: The minimum number of available nodes for Virtual Warehouse autoscaling. + type: int + autoscaling_max_nodes: + description: The maximum number of available nodes for Virtual Warehouse autoscaling. + type: int + common_configs: + description: Configurations that are applied to every application in the Virtual Warehouse service. + type: dict + suboptions: + configBlocks: + description: List of I(ConfigBlocks) for the application. + type: list + elements: dict + suboptions: + id: + description: + - ID of the ConfigBlock. + - Unique within an I(ApplicationConfig). + type: str + format: + description: Format of the ConfigBlock. + type: str + choices: + - HADOOP_XML + - PROPERTIES + - TEXT + - JSON + - BINARY + - ENV + - FLAGFILE + content: + description: Contents of the ConfigBlock. + type: dict + suboptions: + keyValues: + description: Key-value type configuration. + type: dict + text: + description: Text type configuration. + type: str + json: + description: JSON type configuration. + type: str + application_configs: + description: Configurations that are applied to specific applications in the Virtual Warehouse service. + type: dict + suboptions: + __application_name__: + description: The application name or identifier. + type: dict + suboptions: + configBlocks: + description: List of I(ConfigBlocks) for the specified application. + type: list + required: False + elements: dict + suboptions: + id: + description: + - ID of the ConfigBlock. + - Unique within an ApplicationConfig. + type: str + format: + description: Format of ConfigBlock. + type: str + content: + description: Contents of a ConfigBlock. + type: dict + suboptions: + keyValues: + description: Key-value type configuration. + type: dict + text: + description: Text type configuration. + type: str + json: + description: JSON type configuration. + type: str + ldap_groups: + description: LDAP Groupnames to enabled for authentication to the Virtual Warehouse. + type: list + elements: str + enable_sso: + description: Flag to enable Single Sign-On (SSO) for the Virtual Warehouse. + type: bool + default: False + tags: + description: Key-value tags associated with the Virtual Warehouse cloud provider resources. + type: dict + state: + description: The declarative state of the Virtual Warehouse + type: str + default: present + choices: + - present + - absent + wait: + description: + - Flag to enable internal polling to wait for the Virtual Warehouse to achieve the declared state. + - If set to FALSE, the module will return immediately. + type: bool + default: True + delay: + description: + - The internal polling interval (in seconds) while the module waits for the Virtual Warehouse to achieve the declared + state. + type: int + default: 15 + aliases: + - polling_delay + timeout: + description: + - The internal polling timeout (in seconds) while the module waits for the Virtual Warehouse to achieve the declared + state. + type: int + default: 3600 + aliases: + - polling_timeout +extends_documentation_fragment: + - cloudera.cloud.cdp_sdk_options + - cloudera.cloud.cdp_auth_options +''' + +EXAMPLES = r''' +# Note: These examples do not set authentication details. + +# Create a Virtual Warehouse +- cloudera.cloud.dw_virtual_warehouse: + cluster_id: example-cluster-id + name: example-virtual-warehouse + type: hive + template: xsmall + autoscaling_min_nodes: 3 + autoscaling_max_nodes: 19 + tags: + some_key: "some value" + enable_sso: true + ldap_groups: ['group1', 'group2', 'group3'] + +# Create a Virtual Warehouse with configurations +- cloudera.cloud.dw_virtual_warehouse: + cluster_id: example-cluster-id + name: example-virtual-warehouse + type: "hive" + template: "xsmall" + enable_sso: true + ldap_groups: ['group1','group2','group3'] + common_configs: + configBlocks: + - id: das-ranger-policymgr + format: HADOOP_XML + content: + keyValues: + 'xasecure.policymgr.clientssl.truststore': '/path_to_ca_cert/cacerts' + application_configs: + das-webapp: + configBlocks: + - id: hive-kerberos-config + format: TEXT + content: + text: "\n[libdefaults]\n\trenew_lifetime = 7d" + +# Delete a Virtual Warehouse +- cloudera.cloud.dw_virtual_warehouse: + cluster_id: example-cluster-id + warehouse_id: example-virtual-warehouse-id + state: absent +''' + +RETURN = r''' +--- +virtual_warehouse: + description: The details about the CDP Data Warehouse Virtual Warehouse. + type: dict + contains: + id: + description: The identifier of the Virtual Warehouse. + returned: always + type: str + name: + description: The name of the Virtual Warehouse. + returned: always + type: str + vwType: + description: The Virtual Warehouse type. + returned: always + type: str + dbcId: + description: The Database Catalog ID associated with the Virtual Warehouse. + returned: always + type: str + creationDate: + description: The creation time of the Virtual Warehouse in UTC. + returned: always + type: str + status: + description: The status of the Virtual Warehouse. + returned: always + type: str + creator: + description: Details about the Virtual Warehouse creator. + returned: always + type: dict + suboptions: + crn: + description: The creator's Actor CRN. + type: str + returned: always + email: + description: Email address (for users). + type: str + returned: when supported + workloadUsername: + description: Username (for users). + type: str + returned: when supported + machineUsername: + description: Username (for machine users). + type: str + returned: when supported + tags: + description: Custom tags applied to the Virtual Warehouse. + returned: always + type: dict +sdk_out: + description: Returns the captured CDP SDK log. + returned: when supported + type: str +sdk_out_lines: + description: Returns a list of each line of the captured CDP SDK log. + returned: when supported + type: list + elements: str +''' + + +class DwVirtualWarehouse(CdpModule): + def __init__(self, module): + super(DwVirtualWarehouse, self).__init__(module) + + # Set variables + self.warehouse_id = self._get_param('warehouse_id') + self.cluster_id = self._get_param('cluster_id') + self.dbc_id = self._get_param('catalog_id') + self.type = self._get_param('type') + self.name = self._get_param('name') + self.template = self._get_param('template') + self.autoscaling_min_nodes = self._get_param('autoscaling_min_nodes') + self.autoscaling_max_nodes = self._get_param('autoscaling_max_nodes') + self.common_configs = self._get_param('common_configs') + self.application_configs = self._get_param('application_configs') + self.ldap_groups = self._get_param('ldap_groups') + self.enable_sso = self._get_param('enable_sso') + self.state = self._get_param('state') + self.tags = self._get_param('tags') + self.wait = self._get_param('wait') + self.delay = self._get_param('delay') + self.timeout = self._get_param('timeout') + + # Initialize return values + self.virtual_warehouse = {} + + # Initialize internal values + self.target = None + self.changed = False + + # Execute logic process + self.process() + + @CdpModule._Decorators.process_debug + def process(self): + if self.warehouse_id is None: + vws = self.cdpy.dw.list_vws(cluster_id=self.cluster_id) + for vw in vws: + if self.name is not None and vw['name'] == self.name: + self.target = self.cdpy.dw.describe_vw(cluster_id=self.cluster_id, vw_id=vw['id']) + else: + self.target = self.cdpy.dw.describe_vw(cluster_id=self.cluster_id, vw_id=self.warehouse_id) + + if self.target is not None: + # Begin Virtual Warehouse Exists + if self.state == 'absent': + if self.module.check_mode: + self.virtual_warehouse = self.target + else: + # Begin Drop + if self.target['status'] not in self.cdpy.sdk.REMOVABLE_STATES: + self.module.fail_json(msg="Virtual Warehouse not in valid state for Delete operation: %s" % + self.target['status']) + else: + _ = self.cdpy.dw.delete_vw(cluster_id=self.cluster_id, vw_id=self.target['id']) + self.changed = True + if self.wait: + self.cdpy.sdk.wait_for_state( + describe_func=self.cdpy.dw.describe_vw, + params=dict(cluster_id=self.cluster_id, vw_id=self.target['id']), + field=None, delay=self.delay, timeout=self.timeout + ) + else: + self.cdpy.sdk.sleep(self.delay) # Wait for consistency sync + self.virtual_warehouse = self.cdpy.dw.describe_vw(cluster_id=self.cluster_id, vw_id=self.target['id']) + # End Drop + elif self.state == 'present': + # Begin Config check + self.module.warn("Virtual Warehouse already present and reconciliation is not yet implemented") + if self.wait and not self.module.check_mode: + self.target = self.cdpy.sdk.wait_for_state( + describe_func=self.cdpy.dw.describe_vw, + params=dict(cluster_id=self.cluster_id, vw_id=self.target['id']), + state=self.cdpy.sdk.STARTED_STATES + self.cdpy.sdk.STOPPED_STATES, delay=self.delay, + timeout=self.timeout + ) + self.virtual_warehouse = self.target + # End Config check + else: + self.module.fail_json(msg="State %s is not valid for this module" % self.state) + # End Virtual Warehouse Exists + else: + # Begin Virtual Warehouse Not Found + if self.state == 'absent': + self.module.warn("Virtual Warehouse is already absent in Cluster %s" % self.cluster_id) + elif self.state == 'present': + if not self.module.check_mode: + vw_id = self.cdpy.dw.create_vw(cluster_id=self.cluster_id, + dbc_id=self.dbc_id, vw_type=self.type, name=self.name, + template=self.template, + autoscaling_min_cluster=self.autoscaling_min_nodes, + autoscaling_max_cluster=self.autoscaling_max_nodes, + common_configs=self.common_configs, + application_configs=self.application_configs, + ldap_groups=self.ldap_groups, enable_sso=self.enable_sso, + tags=self.tags) + self.changed = True + if self.wait: + self.virtual_warehouse = self.cdpy.sdk.wait_for_state( + describe_func=self.cdpy.dw.describe_vw, + params=dict(cluster_id=self.cluster_id, vw_id=vw_id), + state=self.cdpy.sdk.STARTED_STATES, delay=self.delay, timeout=self.timeout + ) + else: + self.virtual_warehouse = self.cdpy.dw.describe_vw(cluster_id=self.cluster_id, vw_id=vw_id) + else: + self.module.fail_json(msg="State %s is not valid for this module" % self.state) + # End Virtual Warehouse Not Found + +def main(): + module = AnsibleModule( + argument_spec=CdpModule.argument_spec( + warehouse_id=dict(type='str', aliases=['vw_id', 'id']), + cluster_id=dict(required=True, type='str'), + catalog_id=dict(type='str', aliases=['dbc_id']), + type = dict(type='str'), + name = dict(type='str'), + template=dict(type='str', choices=['xsmall', 'small', 'medium', 'large']), + autoscaling_min_nodes=dict(type='int'), + autoscaling_max_nodes=dict(type='int'), + common_configs=dict(type='dict', options=dict( + configBlocks = dict(type='list', elements='dict', options=dict( + id=dict(type='str'), + format=dict(type='str', choices=['HADOOP_XML', 'PROPERTIES', 'TEXT', 'JSON', 'BINARY', 'ENV', 'FLAGFILE']), + content=dict(type='dict', options=dict( + keyValues=dict(type='dict'), + text=dict(type='str'), + json=dict(type='json') + )) + )) + )), + application_configs=dict(type='dict'), + ldap_groups=dict(type='list'), + enable_sso=dict(type='bool', default=False), + tags=dict(type='dict'), + state=dict(type='str', choices=['present', 'absent'], default='present'), + wait = dict(type='bool', default=True), + delay = dict(type='int', aliases=['polling_delay'], default=15), + timeout = dict(type='int', aliases=['polling_timeout'], default=3600) + ), + required_if=[ + ['state', 'absent', ['warehouse_id']], + ['state', 'present', ['catalog_id', 'type', 'name']] + ], + supports_check_mode=True + ) + + result = DwVirtualWarehouse(module) + output = dict(changed=result.changed, virtual_warehouse=result.virtual_warehouse) + + if result.debug: + output.update(sdk_out=result.log_out, sdk_out_lines=result.log_lines) + + module.exit_json(**output) + + +if __name__ == '__main__': + main() diff --git a/plugins/modules/dw_virtual_warehouse_info.py b/plugins/modules/dw_virtual_warehouse_info.py new file mode 100644 index 00000000..0f9808bc --- /dev/null +++ b/plugins/modules/dw_virtual_warehouse_info.py @@ -0,0 +1,242 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright 2021 Cloudera, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cloudera.cloud.plugins.module_utils.cdp_common import CdpModule + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community'} + +DOCUMENTATION = r''' +--- +module: dw_virtual_warehouse_info +short_description: Gather information about CDP Data Warehouse Virtual Warehouses +description: + - Gather information about CDP Virtual Warehouses +author: + - "Webster Mudge (@wmudge)" + - "Dan Chaffelson (@chaffelson)" + - "Saravanan Raju (@raju-saravanan)" +requirements: + - cdpy +options: + warehouse_id: + description: + - The identifier of the Virtual Warehouse. + - Requires I(cluster_id). + - Mutually exclusive with I(name) and I(catalog_id). + type: str + aliases: + - vw_id + - id + cluster_id: + description: + - The identifier of the parent Data Warehouse Cluster of the Virtual Warehouse(s). + type: str + catalog_id: + description: + - The identifier of the parent Database Catalog attached to the Virtual Warehouse(s). + - Requires I(cluster_id). + - Mutally exclusive with I(warehouse_id) and I(name). + type: str + aliases: + - dbc_id + name: + description: + - The name of the Virtual Warehouse. + - Requires I(cluster_id). + - Mutually exclusive with I(warehouse_id) and I(catalog_id). + type: str + delay: + description: + - The internal polling interval (in seconds) while the module waits for the Virtual Warehouse to achieve the declared + state. + type: int + default: 15 + aliases: + - polling_delay + timeout: + description: + - The internal polling timeout (in seconds) while the module waits for the Virtual Warehouse to achieve the declared + state. + type: int + default: 3600 + aliases: + - polling_timeout +extends_documentation_fragment: + - cloudera.cloud.cdp_sdk_options + - cloudera.cloud.cdp_auth_options +''' + +EXAMPLES = r''' +# Note: These examples do not set authentication details. + +# List all Virtual Warehouses in a Cluster +- cloudera.cloud.dw_virtual_warehouse_info: + cluster_id: example-cluster-id + +# List all Virtual Warehouses associated with a Data Catalog +- cloudera.cloud.dw_virtual_warehouse_info: + cluster_id: example-cluster-id + catalog_id: example-data-catalog-id + +# Describe a Virtual Warehouse by ID +- cloudera.cloud.dw_virtual_warehouse_info: + cluster_id: example-cluster-id + warehouse_id: example-virtual-warehouse-id + +# Describe a Virtual Warehouse by name +- cloudera.cloud.dw_virtual_warehouse_info: + cluster_id: example-cluster-id + name: example-virtual-warehouse +''' + +RETURN = r''' +--- +virtual_warehouses: + description: The details about the CDP Data Warehouse Virtual Warehouse(s). + type: list + elements: dict + contains: + id: + description: The identifier of the Virtual Warehouse. + returned: always + type: str + name: + description: The name of the Virtual Warehouse. + returned: always + type: str + vwType: + description: The Virtual Warehouse type. + returned: always + type: str + dbcId: + description: The Database Catalog ID associated with the Virtual Warehouse. + returned: always + type: str + creationDate: + description: The creation time of the Virtual Warehouse in UTC. + returned: always + type: str + status: + description: The status of the Virtual Warehouse. + returned: always + type: str + creator: + description: Details about the Virtual Warehouse creator. + returned: always + type: dict + suboptions: + crn: + description: The creator's Actor CRN. + type: str + returned: always + email: + description: Email address (for users). + type: str + returned: when supported + workloadUsername: + description: Username (for users). + type: str + returned: when supported + machineUsername: + description: Username (for machine users). + type: str + returned: when supported + tags: + description: Custom tags applied to the Virtual Warehouse. + returned: always + type: dict +sdk_out: + description: Returns the captured CDP SDK log. + returned: when supported + type: str +sdk_out_lines: + description: Returns a list of each line of the captured CDP SDK log. + returned: when supported + type: list + elements: str +''' + + +class DwVirtualWarehouseInfo(CdpModule): + def __init__(self, module): + super(DwVirtualWarehouseInfo, self).__init__(module) + + # Set variables + self.warehouse_id = self._get_param('warehouse_id') + self.cluster_id = self._get_param('cluster_id') + self.catalog_id = self._get_param('catalog_id') + self.type = self._get_param('type') + self.name = self._get_param('name') + self.delay = self._get_param('delay') + self.timeout = self._get_param('timeout') + + # Initialize return values + self.virtual_warehouses = [] + + # Execute logic process + self.process() + + @CdpModule._Decorators.process_debug + def process(self): + if self.warehouse_id is not None: + target = self.cdpy.dw.describe_vw(cluster_id=self.cluster_id, vw_id=self.warehouse_id) + if target is not None: + self.virtual_warehouses.append(target) + else: + vws = self.cdpy.dw.list_vws(cluster_id=self.cluster_id) + if self.name is not None: + for vw in vws: + if vw['name'] == self.name: + self.virtual_warehouses.append( + self.cdpy.dw.describe_vw(cluster_id=self.cluster_id, vw_id=vw['id']) + ) + elif self.catalog_id is not None: + self.virtual_warehouses =[v for v in vws if v['dbcId'] == self.catalog_id] + else: + self.virtual_warehouses = vws + + +def main(): + module = AnsibleModule( + argument_spec=CdpModule.argument_spec( + warehouse_id=dict(type='str', aliases=['vw_id', 'id']), + cluster_id=dict(required=True, type='str'), + catalog_id=dict(type='str', aliases=['dbc_id']), + name=dict(type='str'), + delay=dict(type='int', aliases=['polling_delay'], default=15), + timeout=dict(type='int', aliases=['polling_timeout'], default=3600) + ), + mutually_exclusive=[ + ['warehouse_id', 'name', 'catalog_id'] + ], + supports_check_mode=True + ) + + result = DwVirtualWarehouseInfo(module) + output = dict(changed=False, virtual_warehouses=result.virtual_warehouses) + + if result.debug: + output.update(sdk_out=result.log_out, sdk_out_lines=result.log_lines) + + module.exit_json(**output) + + +if __name__ == '__main__': + main()