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,
|
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):
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in a new issue