Adding missing idempotence support in load balancer (#45548)

idempotence
This commit is contained in:
Zim Kalinowski 2018-11-14 16:57:03 +08:00 committed by GitHub
parent 1a3bf09f8a
commit 7db4352f6e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 110 additions and 143 deletions

View file

@ -667,26 +667,8 @@ class AzureRMLoadBalancer(AzureRMModuleBase):
idle_timeout=self.idle_timeout, idle_timeout=self.idle_timeout,
enable_floating_ip=False enable_floating_ip=False
)] if self.protocol else None )] if self.protocol else None
if load_balancer:
# check update, NIE
changed = False
else:
changed = True
elif self.state == 'absent' and load_balancer:
changed = True
self.results['state'] = load_balancer_to_dict(load_balancer) # create new load balancer structure early, so it can be easily compared
if 'tags' in self.results['state']:
update_tags, self.results['state']['tags'] = self.update_tags(self.results['state']['tags'])
if update_tags:
changed = True
else:
if self.tags:
changed = True
self.results['changed'] = changed
if self.state == 'present' and changed:
# create or update
frontend_ip_configurations_param = [self.network_models.FrontendIPConfiguration( frontend_ip_configurations_param = [self.network_models.FrontendIPConfiguration(
name=item.get('name'), name=item.get('name'),
public_ip_address=self.get_public_ip_address_instance(item.get('public_ip_address')) if item.get('public_ip_address') else None, public_ip_address=self.get_public_ip_address_instance(item.get('public_ip_address')) if item.get('public_ip_address') else None,
@ -756,7 +738,7 @@ class AzureRMLoadBalancer(AzureRMModuleBase):
enable_floating_ip=item.get('enable_floating_ip') enable_floating_ip=item.get('enable_floating_ip')
) for item in self.load_balancing_rules] if self.load_balancing_rules else None ) for item in self.load_balancing_rules] if self.load_balancing_rules else None
param = self.network_models.LoadBalancer( self.new_load_balancer = self.network_models.LoadBalancer(
sku=self.network_models.LoadBalancerSku(self.sku) if self.sku else None, sku=self.network_models.LoadBalancerSku(self.sku) if self.sku else None,
location=self.location, location=self.location,
tags=self.tags, tags=self.tags,
@ -767,7 +749,31 @@ class AzureRMLoadBalancer(AzureRMModuleBase):
load_balancing_rules=load_balancing_rules_param load_balancing_rules=load_balancing_rules_param
) )
self.results['state'] = self.create_or_update_load_balancer(param) if load_balancer:
new_dict = self.new_load_balancer.as_dict()
if (self.location != load_balancer['location'] or
self.sku != load_balancer['sku']['name'] or
not default_compare(new_dict, load_balancer, '')):
changed = True
else:
changed = False
else:
changed = True
elif self.state == 'absent' and load_balancer:
changed = True
self.results['state'] = load_balancer if load_balancer else {}
if 'tags' in self.results['state']:
update_tags, self.results['state']['tags'] = self.update_tags(self.results['state']['tags'])
if update_tags:
changed = True
else:
if self.tags:
changed = True
self.results['changed'] = changed
if self.state == 'present' and changed:
self.results['state'] = self.create_or_update_load_balancer(self.new_load_balancer)
elif self.state == 'absent' and changed: elif self.state == 'absent' and changed:
self.delete_load_balancer() self.delete_load_balancer()
self.results['state'] = None self.results['state'] = None
@ -784,7 +790,7 @@ class AzureRMLoadBalancer(AzureRMModuleBase):
"""Get a load balancer""" """Get a load balancer"""
self.log('Fetching loadbalancer {0}'.format(self.name)) self.log('Fetching loadbalancer {0}'.format(self.name))
try: try:
return self.network_client.load_balancers.get(self.resource_group, self.name) return self.network_client.load_balancers.get(self.resource_group, self.name).as_dict()
except CloudError: except CloudError:
return None return None
@ -801,130 +807,39 @@ class AzureRMLoadBalancer(AzureRMModuleBase):
try: try:
poller = self.network_client.load_balancers.create_or_update(self.resource_group, self.name, param) poller = self.network_client.load_balancers.create_or_update(self.resource_group, self.name, param)
new_lb = self.get_poller_result(poller) new_lb = self.get_poller_result(poller)
return load_balancer_to_dict(new_lb) return new_lb.as_dict()
except CloudError as exc: except CloudError as exc:
self.fail("Error creating or updating load balancer {0} - {1}".format(self.name, str(exc))) self.fail("Error creating or updating load balancer {0} - {1}".format(self.name, str(exc)))
def load_balancer_to_dict(load_balancer): def default_compare(new, old, path):
"""Seralialize a LoadBalancer object to a dict""" if isinstance(new, dict):
if not load_balancer: if not isinstance(old, dict):
return dict() return False
for k in new.keys():
result = dict( if not default_compare(new.get(k), old.get(k, None), path + '/' + k):
id=load_balancer.id, return False
name=load_balancer.name, return True
location=load_balancer.location, elif isinstance(new, list):
sku=load_balancer.sku.name, if not isinstance(old, list) or len(new) != len(old):
tags=load_balancer.tags, return False
provisioning_state=load_balancer.provisioning_state, if isinstance(old[0], dict):
etag=load_balancer.etag, key = None
frontend_ip_configurations=[], if 'id' in old[0] and 'id' in new[0]:
backend_address_pools=[], key = 'id'
load_balancing_rules=[], elif 'name' in old[0] and 'name' in new[0]:
probes=[], key = 'name'
inbound_nat_rules=[], new = sorted(new, key=lambda x: x.get(key, None))
inbound_nat_pools=[], old = sorted(old, key=lambda x: x.get(key, None))
outbound_nat_rules=[] else:
) new = sorted(new)
old = sorted(old)
if load_balancer.frontend_ip_configurations: for i in range(len(new)):
result['frontend_ip_configurations'] = [dict( if not default_compare(new[i], old[i], path + '/*'):
id=_.id, return False
name=_.name, return True
etag=_.etag, else:
provisioning_state=_.provisioning_state, return new == old
private_ip_address=_.private_ip_address,
private_ip_allocation_method=_.private_ip_allocation_method,
subnet=dict(
id=_.subnet.id,
name=_.subnet.name,
address_prefix=_.subnet.address_prefix
) if _.subnet else None,
public_ip_address=dict(
id=_.public_ip_address.id,
location=_.public_ip_address.location,
public_ip_allocation_method=_.public_ip_address.public_ip_allocation_method,
ip_address=_.public_ip_address.ip_address
) if _.public_ip_address else None
) for _ in load_balancer.frontend_ip_configurations]
if load_balancer.backend_address_pools:
result['backend_address_pools'] = [dict(
id=_.id,
name=_.name,
provisioning_state=_.provisioning_state,
etag=_.etag
) for _ in load_balancer.backend_address_pools]
if load_balancer.load_balancing_rules:
result['load_balancing_rules'] = [dict(
id=_.id,
name=_.name,
protocol=_.protocol,
frontend_ip_configuration_id=_.frontend_ip_configuration.id,
backend_address_pool_id=_.backend_address_pool.id,
probe_id=_.probe.id,
load_distribution=_.load_distribution,
frontend_port=_.frontend_port,
backend_port=_.backend_port,
idle_timeout_in_minutes=_.idle_timeout_in_minutes,
enable_floating_ip=_.enable_floating_ip,
provisioning_state=_.provisioning_state,
etag=_.etag
) for _ in load_balancer.load_balancing_rules]
if load_balancer.probes:
result['probes'] = [dict(
id=_.id,
name=_.name,
protocol=_.protocol,
port=_.port,
interval_in_seconds=_.interval_in_seconds,
number_of_probes=_.number_of_probes,
request_path=_.request_path,
provisioning_state=_.provisioning_state
) for _ in load_balancer.probes]
if load_balancer.inbound_nat_rules:
result['inbound_nat_rules'] = [dict(
id=_.id,
name=_.name,
frontend_ip_configuration_id=_.frontend_ip_configuration.id,
protocol=_.protocol,
frontend_port=_.frontend_port,
backend_port=_.backend_port,
idle_timeout_in_minutes=_.idle_timeout_in_minutes,
enable_floating_point_ip=_.enable_floating_point_ip if hasattr(_, 'enable_floating_point_ip') else False,
provisioning_state=_.provisioning_state,
etag=_.etag
) for _ in load_balancer.inbound_nat_rules]
if load_balancer.inbound_nat_pools:
result['inbound_nat_pools'] = [dict(
id=_.id,
name=_.name,
frontend_ip_configuration_id=_.frontend_ip_configuration.id,
protocol=_.protocol,
frontend_port_range_start=_.frontend_port_range_start,
frontend_port_range_end=_.frontend_port_range_end,
backend_port=_.backend_port,
provisioning_state=_.provisioning_state,
etag=_.etag
) for _ in load_balancer.inbound_nat_pools]
if load_balancer.outbound_nat_rules:
result['outbound_nat_rules'] = [dict(
id=_.id,
name=_.name,
allocated_outbound_ports=_.allocated_outbound_ports,
frontend_ip_configuration_id=_.frontend_ip_configuration.id,
backend_address_pool=_.backend_address_pool.id,
provisioning_state=_.provisioning_state,
etag=_.etag
) for _ in load_balancer.outbound_nat_rules]
return result
def frontend_ip_configuration_id(subscription_id, resource_group_name, load_balancer_name, name): def frontend_ip_configuration_id(subscription_id, resource_group_name, load_balancer_name, name):

View file

@ -85,7 +85,59 @@
assert: assert:
that: that:
- output.changed - output.changed
- output.state.sku == 'Standard' - output.state.sku.name == 'Standard'
- name: create load balancer again to check idempotency
azure_rm_loadbalancer:
resource_group: '{{ resource_group }}'
name: "{{ lbname_b }}"
sku: Standard
public_ip_address: "{{ pipbname }}"
probe_protocol: Tcp
probe_port: 80
probe_interval: 10
probe_fail_count: 3
protocol: Tcp
load_distribution: Default
frontend_port: 80
backend_port: 8080
idle_timeout: 4
natpool_frontend_port_start: 30
natpool_frontend_port_end: 40
natpool_backend_port: 80
natpool_protocol: Tcp
register: output
- name: assert that output has not changed
assert:
that:
- not output.changed
- name: create load balancer again to check idempotency - change something
azure_rm_loadbalancer:
resource_group: '{{ resource_group }}'
name: "{{ lbname_b }}"
sku: Standard
public_ip_address: "{{ pipbname }}"
probe_protocol: Tcp
probe_port: 80
probe_interval: 10
probe_fail_count: 3
protocol: Tcp
load_distribution: Default
frontend_port: 81
backend_port: 8080
idle_timeout: 4
natpool_frontend_port_start: 30
natpool_frontend_port_end: 40
natpool_backend_port: 80
natpool_protocol: Tcp
register: output
- name: assert that output has changed
assert:
that:
- output.changed
- name: delete load balancer - name: delete load balancer
azure_rm_loadbalancer: azure_rm_loadbalancer: