Skip to content

Commit

Permalink
Add Identity support to hdinsight cluster
Browse files Browse the repository at this point in the history
  • Loading branch information
p3ck committed Aug 30, 2024
1 parent 57d7806 commit c5d23cf
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 8 deletions.
67 changes: 63 additions & 4 deletions plugins/modules/azure_rm_hdinsightcluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
choices:
- 'headnode'
- 'workernode'
- 'zookepernode'
- 'zookeepernode'
min_instance_count:
description:
- The minimum instance count of the cluster.
Expand All @@ -109,6 +109,42 @@
description:
- SSH password.
type: str
identity:
description:
- Identity for the HDInsight Cluster.
type: dict
version_added: '2.7.0'
suboptions:
type:
description:
- Type of the managed identity
choices:
- SystemAssigned
- UserAssigned
- SystemAssigned, UserAssigned
- None
default: None
type: str
user_assigned_identities:
description:
- User Assigned Managed Identities and its options
required: false
type: dict
default: {}
suboptions:
id:
description:
- List of the user assigned identities IDs associated to the HDInsight Cluster
required: false
type: list
elements: str
default: []
append:
description:
- If the list of identities has to be appended to current identities (true) or if it has to replace current identities (false)
required: false
type: bool
default: True
storage_accounts:
description:
- The list of storage accounts in the cluster.
Expand Down Expand Up @@ -192,12 +228,13 @@
sample: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.HDInsight/clusters/myCluster
'''

from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase
from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt

try:
from azure.core.polling import LROPoller
from azure.core.exceptions import ResourceNotFoundError
from azure.mgmt.hdinsight import HDInsightManagementClient
from azure.mgmt.hdinsight.models import ClusterIdentity, UserAssignedIdentity
except ImportError:
# This is handled in azure_rm_common
pass
Expand All @@ -207,7 +244,7 @@ class Actions:
NoAction, Create, Update, Delete = range(4)


class AzureRMClusters(AzureRMModuleBase):
class AzureRMClusters(AzureRMModuleBaseExt):
"""Configuration class for an Azure RM Cluster resource"""

def __init__(self):
Expand All @@ -226,6 +263,10 @@ def __init__(self):
cluster_version=dict(
type='str'
),
identity=dict(
type='dict',
options=self.managed_identity_multiple_spec
),
os_type=dict(
type='str',
choices=['linux']
Expand All @@ -242,7 +283,7 @@ def __init__(self):
type='list',
elements='dict',
options=dict(
name=dict(type='str', choices=['headnode', 'workernode', 'zookepernode']),
name=dict(type='str', choices=['headnode', 'workernode', 'zookeepernode']),
min_instance_count=dict(type='int'),
target_instance_count=dict(type='int'),
vm_size=dict(type='str'),
Expand Down Expand Up @@ -282,11 +323,21 @@ def __init__(self):
self.to_do = Actions.NoAction
self.tags_changed = False
self.new_instance_count = None
self.identity = None
self._managed_identity = None

super(AzureRMClusters, self).__init__(derived_arg_spec=self.module_arg_spec,
supports_check_mode=True,
supports_tags=True)

@property
def managed_identity(self):
if not self._managed_identity:
self._managed_identity = {"identity": ClusterIdentity,
"user_assigned": UserAssignedIdentity
}
return self._managed_identity

def exec_module(self, **kwargs):
"""Main module execution method"""

Expand Down Expand Up @@ -331,6 +382,14 @@ def exec_module(self, **kwargs):

old_response = self.get_cluster()

curr_identity = old_response.get('identity') if old_response else None

self.parameters['identity'] = None
if self.identity:
self.update_identity, identity_result = self.update_managed_identity(curr_identity=curr_identity,
new_identity=self.identity)
self.parameters['identity'] = identity_result.as_dict()

if not old_response:
self.log("Cluster instance doesn't exist")
if self.state == 'absent':
Expand Down
2 changes: 2 additions & 0 deletions plugins/modules/azure_rm_hdinsightcluster_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,8 @@ def format_response(self, item):
'cluster_definition': {
'kind': d.get('properties', {}).get('cluster_definition', {}).get('kind')
},
'identity': d.get('identity'),
'cluster_state': d.get('properties', {}).get('cluster_state'),
'compute_profile_roles': [{
'name': item.get('name'),
'target_instance_count': item.get('target_instance_count'),
Expand Down
82 changes: 78 additions & 4 deletions tests/integration/targets/azure_rm_hdinsightcluster/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,31 @@
rpfx: "{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}"
run_once: true

- name: Gather Resource Group info
azure.azcollection.azure_rm_resourcegroup_info:
name: "{{ resource_group }}"
register: __rg_info

- name: Set location based on resource group
ansible.builtin.set_fact:
location: "{{ __rg_info.resourcegroups.0.location }}"

- name: Create identity and policy ids arrays
ansible.builtin.set_fact:
managed_identity_ids: []
access_policies_object_ids: []

- name: Create user managed identities
ansible.builtin.include_tasks: managedidentity.yml
vars:
managed_identity_test_unique: 'hdinsightcluster'
managed_identity_unique: "{{ item }}"
managed_identity_action: 'create'
managed_identity_location: "{{ location }}"
with_items:
- '1'
- '2'

- name: Create storage account
azure_rm_storageaccount:
resource_group: "{{ resource_group }}"
Expand Down Expand Up @@ -31,9 +56,15 @@
resource_group: "{{ resource_group }}"
name: "cluster{{ rpfx }}"
location: eastus2
cluster_version: 3.6
cluster_version: 5.0
os_type: linux
tier: standard
identity:
type: UserAssigned
user_assigned_identities:
id:
- "{{ managed_identity_ids[0] }}"
- "{{ managed_identity_ids[1] }}"
cluster_definition:
kind: spark
gateway_rest_username: http-user
Expand Down Expand Up @@ -74,9 +105,15 @@
resource_group: "{{ resource_group }}"
name: "cluster{{ rpfx }}"
location: eastus2
cluster_version: 3.6
cluster_version: 5.0
os_type: linux
tier: standard
identity:
type: UserAssigned
user_assigned_identities:
id:
- "{{ managed_identity_ids[0] }}"
- "{{ managed_identity_ids[1] }}"
cluster_definition:
kind: spark
gateway_rest_username: http-user
Expand Down Expand Up @@ -112,14 +149,29 @@
that:
- output.changed

- name: Wait for instance of Cluster provisioning to complete
azure_rm_hdinsightcluster_info:
resource_group: "{{ resource_group }}"
name: "cluster{{ rpfx }}"
register: facts
until: facts.clusters[0]['cluster_state'] == 'Running'
retries: 40
delay: 60

- name: Create again instance of Cluster -- idempotent
azure_rm_hdinsightcluster:
resource_group: "{{ resource_group }}"
name: "cluster{{ rpfx }}"
location: eastus2
cluster_version: 3.6
cluster_version: 5.0
os_type: linux
tier: standard
identity:
type: UserAssigned
user_assigned_identities:
id:
- "{{ managed_identity_ids[0] }}"
- "{{ managed_identity_ids[1] }}"
cluster_definition:
kind: spark
gateway_rest_username: http-user
Expand Down Expand Up @@ -159,9 +211,15 @@
resource_group: "{{ resource_group }}"
name: "cluster{{ rpfx }}"
location: eastus2
cluster_version: 3.6
cluster_version: 5.0
os_type: linux
tier: standard
identity:
type: UserAssigned
user_assigned_identities:
id:
- "{{ managed_identity_ids[0] }}"
- "{{ managed_identity_ids[1] }}"
cluster_definition:
kind: spark
gateway_rest_username: http-user
Expand Down Expand Up @@ -221,6 +279,11 @@
- output.clusters[0]['cluster_definition'] != None
- output.clusters[0]['compute_profile_roles'] != None
- output.clusters[0]['connectivity_endpoints'] != None
- output.clusters[0]['identity'] != None
- output.clusters[0]['identity']['type'] == 'UserAssigned'
- output.clusters[0]['identity']['user_assigned_identities'] | length == 2
- managed_identity_ids[0] | lower in output.clusters[0].identity.user_assigned_identities
- managed_identity_ids[1] | lower in output.clusters[0].identity.user_assigned_identities

- name: Delete instance of Cluster -- check mode
azure_rm_hdinsightcluster:
Expand All @@ -244,3 +307,14 @@
ansible.builtin.assert:
that:
- output.changed

- name: Delete user managed identities
ansible.builtin.include_tasks: managedidentity.yml
vars:
managed_identity_test_unique: 'hdinsightcluster'
managed_identity_unique: "{{ item }}"
managed_identity_action: 'delete'
managed_identity_location: "{{ location }}"
with_items:
- '1'
- '2'
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
- name: Set user managed identity name
ansible.builtin.set_fact:
identity_name: "ansible-test-{{ managed_identity_test_unique }}-identity-{{ managed_identity_unique }}"

- name: Set user managed identity ID base path
ansible.builtin.set_fact:
base_path: "/subscriptions/{{ azure_subscription_id }}/resourcegroups/{{ resource_group }}"

- name: Set user managed identity ID
ansible.builtin.set_fact:
identity_id: "{{ base_path }}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{{ identity_name }}"

- name: Set managed identity ID into the ids list.
ansible.builtin.set_fact:
managed_identity_ids: "{{ managed_identity_ids + [identity_id] }}"
when: managed_identity_action == 'create'

- name: Create the user managed identity - {{ identity_name }}
azure_rm_resource:
resource_group: "{{ resource_group }}"
provider: ManagedIdentity
resource_type: userAssignedIdentities
resource_name: "{{ identity_name }}"
api_version: "2023-01-31"
body:
location: "{{ managed_identity_location }}"
state: present
when: managed_identity_action == 'create'

- name: Lookup service principal object id for identity {{ identity_name }}
azure_rm_resource_info:
api_version: "2023-01-31"
resource_group: "{{ resource_group }}"
provider: ManagedIdentity
resource_type: userAssignedIdentities
resource_name: "{{ identity_name }}"
register: output
when:
- access_policies_object_ids is defined
- managed_identity_action == 'create'

- name: Set object ID for identity {{ identity_name }}
ansible.builtin.set_fact:
access_policies_object_ids: "{{ access_policies_object_ids + [output.response[0].properties.principalId] }}"
when:
- access_policies_object_ids is defined
- managed_identity_action == 'create'

- name: Destroy the user managed identity - {{ identity_name }}
azure_rm_resource:
resource_group: "{{ resource_group }}"
provider: ManagedIdentity
resource_type: userAssignedIdentities
resource_name: "{{ identity_name }}"
api_version: "2023-01-31"
state: absent
when: managed_identity_action == 'delete'

0 comments on commit c5d23cf

Please sign in to comment.