Adding missing idempotence support in load balancer (#45548)
idempotence
This commit is contained in:
parent
1a3bf09f8a
commit
7db4352f6e
2 changed files with 110 additions and 143 deletions
|
@ -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…
Reference in a new issue