Skip to content

Commit cc9d8dc

Browse files
Fix NoneType errors with elb_classic_lb (#915) (#919)
[PR #915/8ce9c198 backport][stable-3] Fix NoneType errors with elb_classic_lb This is a backport of PR #915 as merged into main (8ce9c19). SUMMARY fixes: #589 fixes: #914 Fixes two NoneType related bugs when creating new ELBs. (includes extra tests this time to trigger the bugs) ISSUE TYPE Bugfix Pull Request COMPONENT NAME plugins/modules/elb_classic_lb.py ADDITIONAL INFORMATION Reviewed-by: Mark Chappell <None>
1 parent 6c31378 commit cc9d8dc

File tree

4 files changed

+336
-2
lines changed

4 files changed

+336
-2
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
bugfixes:
2+
- elb_classic_lb - fix ``'NoneType' object has no attribute`` bug when creating a new ELB using security group names (https://github.com/ansible-collections/amazon.aws/issues/914).
3+
- elb_classic_lb - fix ``'NoneType' object has no attribute`` bug when creating a new ELB in check mode with a health check (https://github.com/ansible-collections/amazon.aws/pull/915).

plugins/modules/elb_classic_lb.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -744,7 +744,7 @@ def __init__(self, module):
744744
if security_group_names:
745745
# Use the subnets attached to the VPC to find which VPC we're in and
746746
# limit the search
747-
if self.elb.get('Subnets', None):
747+
if self.elb and self.elb.get('Subnets', None):
748748
subnets = set(self.elb.get('Subnets') + list(self.subnets or []))
749749
else:
750750
subnets = set(self.subnets)
@@ -1440,7 +1440,7 @@ def _set_health_check(self):
14401440
"""Set health check values on ELB as needed"""
14411441
health_check_config = self._format_healthcheck()
14421442

1443-
if health_check_config == self.elb['HealthCheck']:
1443+
if self.elb and health_check_config == self.elb['HealthCheck']:
14441444
return False
14451445

14461446
self.changed = True
Lines changed: 330 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,330 @@
1+
---
2+
- block:
3+
- name: Create ELB for testing complex updates (CHECK)
4+
elb_classic_lb:
5+
name: "{{ elb_name }}"
6+
state: present
7+
# zones: ['{{ availability_zone_a }}', '{{ availability_zone_b }}']
8+
listeners: '{{ default_listeners }}'
9+
health_check: '{{ default_health_check }}'
10+
wait: true
11+
scheme: 'internal'
12+
subnets: ['{{ subnet_a }}', '{{ subnet_b }}']
13+
security_group_names: ['{{ resource_prefix }}-a', '{{ resource_prefix }}-b']
14+
tags: '{{ default_tags }}'
15+
cross_az_load_balancing: True
16+
idle_timeout: '{{ default_idle_timeout }}'
17+
connection_draining_timeout: '{{ default_drain_timeout }}'
18+
access_logs:
19+
interval: '{{ default_logging_interval }}'
20+
s3_location: '{{ s3_logging_bucket_a }}'
21+
s3_prefix: '{{ default_logging_prefix }}'
22+
enabled: true
23+
register: result
24+
check_mode: True
25+
26+
- name: Verify that we expect to change
27+
assert:
28+
that:
29+
- result is changed
30+
31+
- name: Create ELB for testing complex updates
32+
elb_classic_lb:
33+
name: "{{ elb_name }}"
34+
state: present
35+
# zones: ['{{ availability_zone_a }}', '{{ availability_zone_b }}']
36+
listeners: '{{ default_listeners }}'
37+
health_check: '{{ default_health_check }}'
38+
wait: true
39+
scheme: 'internal'
40+
subnets: ['{{ subnet_a }}', '{{ subnet_b }}']
41+
security_group_names: ['{{ resource_prefix }}-a', '{{ resource_prefix }}-b']
42+
tags: '{{ default_tags }}'
43+
cross_az_load_balancing: True
44+
idle_timeout: '{{ default_idle_timeout }}'
45+
connection_draining_timeout: '{{ default_drain_timeout }}'
46+
access_logs:
47+
interval: '{{ default_logging_interval }}'
48+
s3_location: '{{ s3_logging_bucket_a }}'
49+
s3_prefix: '{{ default_logging_prefix }}'
50+
enabled: true
51+
register: result
52+
53+
- name: Verify that simple parameters were set
54+
assert:
55+
that:
56+
- result is changed
57+
- result.elb.status == "created"
58+
- availability_zone_a in result.elb.zones
59+
- availability_zone_b in result.elb.zones
60+
- subnet_a in result.elb.subnets
61+
- subnet_b in result.elb.subnets
62+
- default_listener_tuples[0] in result.elb.listeners
63+
- default_listener_tuples[1] in result.elb.listeners
64+
- sg_a in result.elb.security_group_ids
65+
- sg_b in result.elb.security_group_ids
66+
- sg_c not in result.elb.security_group_ids
67+
- result.elb.health_check.healthy_threshold == default_health_check['healthy_threshold']
68+
- result.elb.health_check.interval == default_health_check['interval']
69+
- result.elb.health_check.target == default_health_check_target
70+
- result.elb.health_check.timeout == default_health_check['response_timeout']
71+
- result.elb.health_check.unhealthy_threshold == default_health_check['unhealthy_threshold']
72+
- result.elb.tags == default_tags
73+
- result.elb.cross_az_load_balancing == 'yes'
74+
- result.elb.idle_timeout == default_idle_timeout
75+
- result.elb.connection_draining_timeout == default_drain_timeout
76+
- result.elb.proxy_policy == None
77+
- result.load_balancer.load_balancer_attributes.access_log.emit_interval == default_logging_interval
78+
- result.load_balancer.load_balancer_attributes.access_log.s3_bucket_name == s3_logging_bucket_a
79+
- result.load_balancer.load_balancer_attributes.access_log.s3_bucket_prefix == default_logging_prefix
80+
- result.load_balancer.load_balancer_attributes.access_log.enabled == True
81+
82+
- name: Create ELB for testing complex updates - idempotency (CHECK)
83+
elb_classic_lb:
84+
name: "{{ elb_name }}"
85+
state: present
86+
# zones: ['{{ availability_zone_a }}', '{{ availability_zone_b }}']
87+
listeners: '{{ default_listeners }}'
88+
health_check: '{{ default_health_check }}'
89+
wait: true
90+
scheme: 'internal'
91+
subnets: ['{{ subnet_a }}', '{{ subnet_b }}']
92+
security_group_names: ['{{ resource_prefix }}-a', '{{ resource_prefix }}-b']
93+
tags: '{{ default_tags }}'
94+
cross_az_load_balancing: True
95+
idle_timeout: '{{ default_idle_timeout }}'
96+
connection_draining_timeout: '{{ default_drain_timeout }}'
97+
access_logs:
98+
interval: '{{ default_logging_interval }}'
99+
s3_location: '{{ s3_logging_bucket_a }}'
100+
s3_prefix: '{{ default_logging_prefix }}'
101+
enabled: true
102+
register: result
103+
check_mode: True
104+
105+
- name: Verify that we expect to not change
106+
assert:
107+
that:
108+
- result is not changed
109+
110+
- name: Create ELB for testing complex updates - idempotency
111+
elb_classic_lb:
112+
name: "{{ elb_name }}"
113+
state: present
114+
# zones: ['{{ availability_zone_a }}', '{{ availability_zone_b }}']
115+
listeners: '{{ default_listeners }}'
116+
health_check: '{{ default_health_check }}'
117+
wait: true
118+
scheme: 'internal'
119+
subnets: ['{{ subnet_a }}', '{{ subnet_b }}']
120+
security_group_names: ['{{ resource_prefix }}-a', '{{ resource_prefix }}-b']
121+
tags: '{{ default_tags }}'
122+
cross_az_load_balancing: True
123+
idle_timeout: '{{ default_idle_timeout }}'
124+
connection_draining_timeout: '{{ default_drain_timeout }}'
125+
access_logs:
126+
interval: '{{ default_logging_interval }}'
127+
s3_location: '{{ s3_logging_bucket_a }}'
128+
s3_prefix: '{{ default_logging_prefix }}'
129+
enabled: true
130+
register: result
131+
132+
- name: Verify that simple parameters were set
133+
assert:
134+
that:
135+
- result is not changed
136+
- result.elb.status == "exists"
137+
- availability_zone_a in result.elb.zones
138+
- availability_zone_b in result.elb.zones
139+
- subnet_a in result.elb.subnets
140+
- subnet_b in result.elb.subnets
141+
- default_listener_tuples[0] in result.elb.listeners
142+
- default_listener_tuples[1] in result.elb.listeners
143+
- sg_a in result.elb.security_group_ids
144+
- sg_b in result.elb.security_group_ids
145+
- sg_c not in result.elb.security_group_ids
146+
- result.elb.health_check.healthy_threshold == default_health_check['healthy_threshold']
147+
- result.elb.health_check.interval == default_health_check['interval']
148+
- result.elb.health_check.target == default_health_check_target
149+
- result.elb.health_check.timeout == default_health_check['response_timeout']
150+
- result.elb.health_check.unhealthy_threshold == default_health_check['unhealthy_threshold']
151+
- result.elb.tags == default_tags
152+
- result.elb.cross_az_load_balancing == 'yes'
153+
- result.elb.idle_timeout == default_idle_timeout
154+
- result.elb.connection_draining_timeout == default_drain_timeout
155+
- result.elb.proxy_policy == None
156+
- result.load_balancer.load_balancer_attributes.access_log.emit_interval == default_logging_interval
157+
- result.load_balancer.load_balancer_attributes.access_log.s3_bucket_name == s3_logging_bucket_a
158+
- result.load_balancer.load_balancer_attributes.access_log.s3_bucket_prefix == default_logging_prefix
159+
- result.load_balancer.load_balancer_attributes.access_log.enabled == True
160+
161+
###
162+
163+
- name: Perform complex update (CHECK)
164+
elb_classic_lb:
165+
name: "{{ elb_name }}"
166+
state: present
167+
# zones: ['{{ availability_zone_a }}', '{{ availability_zone_b }}']
168+
listeners: '{{ updated_listeners }}'
169+
health_check: '{{ updated_health_check }}'
170+
wait: true
171+
scheme: 'internal'
172+
subnets: ['{{ subnet_a }}', '{{ subnet_b }}']
173+
security_group_names: ['{{ resource_prefix }}-c', '{{ resource_prefix }}-b']
174+
tags: '{{ updated_tags }}'
175+
cross_az_load_balancing: False
176+
idle_timeout: '{{ updated_idle_timeout }}'
177+
connection_draining_timeout: '{{ default_drain_timeout }}'
178+
access_logs:
179+
interval: '{{ updated_logging_interval }}'
180+
s3_location: '{{ s3_logging_bucket_a }}'
181+
s3_prefix: '{{ default_logging_prefix }}'
182+
enabled: true
183+
register: result
184+
check_mode: True
185+
186+
- name: Verify that we expect to change
187+
assert:
188+
that:
189+
- result is changed
190+
191+
- name: Perform complex update
192+
elb_classic_lb:
193+
name: "{{ elb_name }}"
194+
state: present
195+
# zones: ['{{ availability_zone_a }}', '{{ availability_zone_b }}']
196+
listeners: '{{ updated_listeners }}'
197+
health_check: '{{ updated_health_check }}'
198+
wait: true
199+
scheme: 'internal'
200+
subnets: ['{{ subnet_a }}', '{{ subnet_b }}']
201+
security_group_names: ['{{ resource_prefix }}-c', '{{ resource_prefix }}-b']
202+
tags: '{{ updated_tags }}'
203+
cross_az_load_balancing: False
204+
idle_timeout: '{{ updated_idle_timeout }}'
205+
connection_draining_timeout: '{{ default_drain_timeout }}'
206+
access_logs:
207+
interval: '{{ updated_logging_interval }}'
208+
s3_location: '{{ s3_logging_bucket_a }}'
209+
s3_prefix: '{{ default_logging_prefix }}'
210+
enabled: true
211+
register: result
212+
213+
- name: Verify that simple parameters were set
214+
assert:
215+
that:
216+
- result is changed
217+
- result.elb.status == "exists"
218+
- availability_zone_a in result.elb.zones
219+
- availability_zone_b in result.elb.zones
220+
- subnet_a in result.elb.subnets
221+
- subnet_b in result.elb.subnets
222+
- updated_listener_tuples[0] in result.elb.listeners
223+
- updated_listener_tuples[1] in result.elb.listeners
224+
- sg_a not in result.elb.security_group_ids
225+
- sg_b in result.elb.security_group_ids
226+
- sg_c in result.elb.security_group_ids
227+
- result.elb.health_check.healthy_threshold == updated_health_check['healthy_threshold']
228+
- result.elb.health_check.interval == updated_health_check['interval']
229+
- result.elb.health_check.target == updated_health_check_target
230+
- result.elb.health_check.timeout == updated_health_check['response_timeout']
231+
- result.elb.health_check.unhealthy_threshold == updated_health_check['unhealthy_threshold']
232+
- result.elb.tags == updated_tags
233+
- result.elb.cross_az_load_balancing == 'no'
234+
- result.elb.idle_timeout == updated_idle_timeout
235+
- result.elb.connection_draining_timeout == default_drain_timeout
236+
- result.elb.proxy_policy == None
237+
- result.load_balancer.load_balancer_attributes.access_log.emit_interval == updated_logging_interval
238+
- result.load_balancer.load_balancer_attributes.access_log.s3_bucket_name == s3_logging_bucket_a
239+
- result.load_balancer.load_balancer_attributes.access_log.s3_bucket_prefix == default_logging_prefix
240+
- result.load_balancer.load_balancer_attributes.access_log.enabled == True
241+
242+
- name: Perform complex update idempotency (CHECK)
243+
elb_classic_lb:
244+
name: "{{ elb_name }}"
245+
state: present
246+
# zones: ['{{ availability_zone_a }}', '{{ availability_zone_b }}']
247+
listeners: '{{ updated_listeners }}'
248+
health_check: '{{ updated_health_check }}'
249+
wait: true
250+
scheme: 'internal'
251+
subnets: ['{{ subnet_a }}', '{{ subnet_b }}']
252+
security_group_names: ['{{ resource_prefix }}-c', '{{ resource_prefix }}-b']
253+
tags: '{{ updated_tags }}'
254+
cross_az_load_balancing: False
255+
idle_timeout: '{{ updated_idle_timeout }}'
256+
connection_draining_timeout: '{{ default_drain_timeout }}'
257+
access_logs:
258+
interval: '{{ updated_logging_interval }}'
259+
s3_location: '{{ s3_logging_bucket_a }}'
260+
s3_prefix: '{{ default_logging_prefix }}'
261+
enabled: true
262+
register: result
263+
check_mode: True
264+
265+
- name: Verify we expect to not change
266+
assert:
267+
that:
268+
- result is not changed
269+
270+
- name: Perform complex update - idempotency
271+
elb_classic_lb:
272+
name: "{{ elb_name }}"
273+
state: present
274+
# zones: ['{{ availability_zone_a }}', '{{ availability_zone_b }}']
275+
listeners: '{{ updated_listeners }}'
276+
health_check: '{{ updated_health_check }}'
277+
wait: true
278+
scheme: 'internal'
279+
subnets: ['{{ subnet_a }}', '{{ subnet_b }}']
280+
security_group_names: ['{{ resource_prefix }}-c', '{{ resource_prefix }}-b']
281+
tags: '{{ updated_tags }}'
282+
cross_az_load_balancing: False
283+
idle_timeout: '{{ updated_idle_timeout }}'
284+
connection_draining_timeout: '{{ default_drain_timeout }}'
285+
access_logs:
286+
interval: '{{ updated_logging_interval }}'
287+
s3_location: '{{ s3_logging_bucket_a }}'
288+
s3_prefix: '{{ default_logging_prefix }}'
289+
enabled: true
290+
register: result
291+
292+
- name: Verify that simple parameters were set
293+
assert:
294+
that:
295+
- result is not changed
296+
- result.elb.status == "exists"
297+
- availability_zone_a in result.elb.zones
298+
- availability_zone_b in result.elb.zones
299+
- subnet_a in result.elb.subnets
300+
- subnet_b in result.elb.subnets
301+
- updated_listener_tuples[0] in result.elb.listeners
302+
- updated_listener_tuples[1] in result.elb.listeners
303+
- sg_a not in result.elb.security_group_ids
304+
- sg_b in result.elb.security_group_ids
305+
- sg_c in result.elb.security_group_ids
306+
- result.elb.health_check.healthy_threshold == updated_health_check['healthy_threshold']
307+
- result.elb.health_check.interval == updated_health_check['interval']
308+
- result.elb.health_check.target == updated_health_check_target
309+
- result.elb.health_check.timeout == updated_health_check['response_timeout']
310+
- result.elb.health_check.unhealthy_threshold == updated_health_check['unhealthy_threshold']
311+
- result.elb.tags == updated_tags
312+
- result.elb.cross_az_load_balancing == 'no'
313+
- result.elb.idle_timeout == updated_idle_timeout
314+
- result.elb.connection_draining_timeout == default_drain_timeout
315+
- result.elb.proxy_policy == None
316+
- result.load_balancer.load_balancer_attributes.access_log.emit_interval == updated_logging_interval
317+
- result.load_balancer.load_balancer_attributes.access_log.s3_bucket_name == s3_logging_bucket_a
318+
- result.load_balancer.load_balancer_attributes.access_log.s3_bucket_prefix == default_logging_prefix
319+
- result.load_balancer.load_balancer_attributes.access_log.enabled == True
320+
321+
always:
322+
323+
# ============================================================
324+
- name: remove the test load balancer
325+
elb_classic_lb:
326+
name: "{{ elb_name }}"
327+
state: absent
328+
wait: true
329+
register: result
330+
ignore_errors: true

tests/integration/targets/elb_classic_lb/tasks/main.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
- include_tasks: schema_change.yml
3737

3838
- include_tasks: simple_changes.yml
39+
- include_tasks: complex_changes.yml
3940

4041
always:
4142

0 commit comments

Comments
 (0)