Adding missing idempotence support in load balancer (#45548)

idempotence
pull/48654/head
Zim Kalinowski 6 years ago committed by GitHub
parent 1a3bf09f8a
commit 7db4352f6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -667,26 +667,8 @@ class AzureRMLoadBalancer(AzureRMModuleBase):
idle_timeout=self.idle_timeout,
enable_floating_ip=False
)] 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)
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
# create new load balancer structure early, so it can be easily compared
frontend_ip_configurations_param = [self.network_models.FrontendIPConfiguration(
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,
@ -756,7 +738,7 @@ class AzureRMLoadBalancer(AzureRMModuleBase):
enable_floating_ip=item.get('enable_floating_ip')
) 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,
location=self.location,
tags=self.tags,
@ -767,7 +749,31 @@ class AzureRMLoadBalancer(AzureRMModuleBase):
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:
self.delete_load_balancer()
self.results['state'] = None
@ -784,7 +790,7 @@ class AzureRMLoadBalancer(AzureRMModuleBase):
"""Get a load balancer"""
self.log('Fetching loadbalancer {0}'.format(self.name))
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:
return None
@ -801,130 +807,39 @@ class AzureRMLoadBalancer(AzureRMModuleBase):
try:
poller = self.network_client.load_balancers.create_or_update(self.resource_group, self.name, param)
new_lb = self.get_poller_result(poller)
return load_balancer_to_dict(new_lb)
return new_lb.as_dict()
except CloudError as exc:
self.fail("Error creating or updating load balancer {0} - {1}".format(self.name, str(exc)))
def load_balancer_to_dict(load_balancer):
"""Seralialize a LoadBalancer object to a dict"""
if not load_balancer:
return dict()
result = dict(
id=load_balancer.id,
name=load_balancer.name,
location=load_balancer.location,
sku=load_balancer.sku.name,
tags=load_balancer.tags,
provisioning_state=load_balancer.provisioning_state,
etag=load_balancer.etag,
frontend_ip_configurations=[],
backend_address_pools=[],
load_balancing_rules=[],
probes=[],
inbound_nat_rules=[],
inbound_nat_pools=[],
outbound_nat_rules=[]
)
if load_balancer.frontend_ip_configurations:
result['frontend_ip_configurations'] = [dict(
id=_.id,
name=_.name,
etag=_.etag,
provisioning_state=_.provisioning_state,
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 default_compare(new, old, path):
if isinstance(new, dict):
if not isinstance(old, dict):
return False
for k in new.keys():
if not default_compare(new.get(k), old.get(k, None), path + '/' + k):
return False
return True
elif isinstance(new, list):
if not isinstance(old, list) or len(new) != len(old):
return False
if isinstance(old[0], dict):
key = None
if 'id' in old[0] and 'id' in new[0]:
key = 'id'
elif 'name' in old[0] and 'name' in new[0]:
key = 'name'
new = sorted(new, key=lambda x: x.get(key, None))
old = sorted(old, key=lambda x: x.get(key, None))
else:
new = sorted(new)
old = sorted(old)
for i in range(len(new)):
if not default_compare(new[i], old[i], path + '/*'):
return False
return True
else:
return new == old
def frontend_ip_configuration_id(subscription_id, resource_group_name, load_balancer_name, name):

@ -85,7 +85,59 @@
assert:
that:
- 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
azure_rm_loadbalancer:

Loading…
Cancel
Save