Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
configuration
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenEdx
configuration
Commits
baadf3e3
Commit
baadf3e3
authored
9 years ago
by
Feanil Patel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update to latest ec2_elb_lb.
parent
87473da7
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
1 additions
and
648 deletions
+1
-648
playbooks/edx-east/edx_service.yml
+1
-1
playbooks/library/ec2_elb_lb_1.8
+0
-647
No files found.
playbooks/edx-east/edx_service.yml
View file @
baadf3e3
...
...
@@ -106,7 +106,7 @@
# target: "local" # simplifying generalization of instnace-id, gateway-id or local
-
name
:
Manage ELB
ec2_elb_lb
_1.8
:
ec2_elb_lb
:
profile
:
"
{{
profile
}}"
region
:
"
{{
aws_region
}}"
scheme
:
"
{{
elb_scheme
}}"
...
...
This diff is collapsed.
Click to expand it.
playbooks/library/ec2_elb_lb_1.8
deleted
100644 → 0
View file @
87473da7
#!/usr/bin/python
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
DOCUMENTATION
=
"""
---
module: ec2_elb_lb
description: Creates or destroys Amazon ELB.
short_description: Creates or destroys Amazon ELB.
- Returns information about the load balancer.
- Will be marked changed when called only if state is changed.
version_added: "1.5"
author: Jim Dalton
options:
state:
description:
- Create or destroy the ELB
required: true
name:
description:
- The name of the ELB
required: true
listeners:
description:
- List of ports/protocols for this ELB to listen on (see example)
required: false
purge_listeners:
description:
- Purge existing listeners on ELB that are not found in listeners
required: false
default: true
zones:
description:
- List of availability zones to enable on this ELB
required: false
purge_zones:
description:
- Purge existing availability zones on ELB that are not found in zones
required: false
default: false
security_group_ids:
description:
- A list of security groups to apply to the elb
require: false
default: None
version_added: "1.6"
health_check:
description:
- An associative array of health check configuration settigs (see example)
require: false
default: None
region:
description:
- The AWS region to use. If not specified then the value of the EC2_REGION environment variable, if any, is used.
required: false
aliases: ['aws_region', 'ec2_region']
subnets:
description:
- A list of VPC subnets to use when creating ELB. Zones should be empty if using this.
required: false
default: None
aliases: []
version_added: "1.6"
purge_subnets:
description:
- Purge existing subnet on ELB that are not found in subnets
required: false
default: false
scheme:
description:
- The scheme to use when creating the ELB. For a private VPC-visible ELB use 'internal'.
required: false
default: 'internet-facing'
validate_certs:
description:
- When set to "no", SSL certificates will not be validated for boto versions >= 2.6.0.
required: false
default: "yes"
choices: ["yes", "no"]
aliases: []
version_added: "1.5"
extends_documentation_fragment: aws
"""
EXAMPLES
=
"""
# Note: None of these examples set aws_access_key, aws_secret_key, or region.
# It is assumed that their matching environment variables are set.
# Basic provisioning example
- local_action:
module: ec2_elb_lb
name: "test-please-delete"
state: present
zones:
- us-east-1a
- us-east-1d
listeners:
- protocol: http # options are http, https, ssl, tcp
load_balancer_port: 80
instance_port: 80
- protocol: https
load_balancer_port: 443
instance_protocol: http # optional, defaults to value of protocol setting
instance_port: 80
# ssl certificate required for https or ssl
ssl_certificate_id: "arn:aws:iam::123456789012:server-certificate/company/servercerts/ProdServerCert"
# Basic VPC provisioning example
- local_action:
module: ec2_elb_lb
name: "test-vpc"
scheme: internal
state: present
subnets:
- subnet-abcd1234
- subnet-1a2b3c4d
listeners:
- protocol: http # options are http, https, ssl, tcp
load_balancer_port: 80
instance_port: 80
# Configure a health check
- local_action:
module: ec2_elb_lb
name: "test-please-delete"
state: present
zones:
- us-east-1d
listeners:
- protocol: http
load_balancer_port: 80
instance_port: 80
health_check:
ping_protocol: http # options are http, https, ssl, tcp
ping_port: 80
ping_path: "/index.html" # not required for tcp or ssl
response_timeout: 5 # seconds
interval: 30 # seconds
unhealthy_threshold: 2
healthy_threshold: 10
# Ensure ELB is gone
- local_action:
module: ec2_elb_lb
name: "test-please-delete"
state: absent
# Normally, this module will purge any listeners that exist on the ELB
# but aren't specified in the listeners parameter. If purge_listeners is
# false it leaves them alone
- local_action:
module: ec2_elb_lb
name: "test-please-delete"
state: present
zones:
- us-east-1a
- us-east-1d
listeners:
- protocol: http
load_balancer_port: 80
instance_port: 80
purge_listeners: no
# Normally, this module will leave availability zones that are enabled
# on the ELB alone. If purge_zones is true, then any extreneous zones
# will be removed
- local_action:
module: ec2_elb_lb
name: "test-please-delete"
state: present
zones:
- us-east-1a
- us-east-1d
listeners:
- protocol: http
load_balancer_port: 80
instance_port: 80
purge_zones: yes
# Creates a ELB and assigns a list of subnets to it.
- local_action:
module: ec2_elb_lb
state: present
name: 'New ELB'
security_group_ids: 'sg-123456, sg-67890'
region: us-west-2
subnets: 'subnet-123456, subnet-67890'
purge_subnets: yes
listeners:
- protocol: http
load_balancer_port: 80
instance_port: 80
"""
import
sys
import
os
try
:
import
boto
import
boto.ec2.elb
from
boto.ec2.elb.healthcheck
import
HealthCheck
from
boto.regioninfo
import
RegionInfo
except
ImportError
:
print
"failed=True msg='boto required for this module'"
sys
.
exit
(
1
)
class
ElbManager
(
object
):
"""Handles ELB creation and destruction"""
def
__init__
(
self
,
module
,
name
,
listeners
=
None
,
purge_listeners
=
None
,
zones
=
None
,
purge_zones
=
None
,
security_group_ids
=
None
,
health_check
=
None
,
subnets
=
None
,
purge_subnets
=
None
,
scheme
=
"internet-facing"
,
tags
=
[],
region
=
None
,
**
aws_connect_params
):
self
.
module
=
module
self
.
name
=
name
self
.
listeners
=
listeners
self
.
purge_listeners
=
purge_listeners
self
.
zones
=
zones
self
.
purge_zones
=
purge_zones
self
.
security_group_ids
=
security_group_ids
self
.
health_check
=
health_check
self
.
subnets
=
subnets
self
.
purge_subnets
=
purge_subnets
self
.
scheme
=
scheme
self
.
tags
=
tags
self
.
aws_connect_params
=
aws_connect_params
self
.
region
=
region
self
.
changed
=
False
self
.
status
=
'gone'
self
.
elb_conn
=
self
.
_get_elb_connection
()
self
.
elb
=
self
.
_get_elb
()
def
ensure_ok
(
self
):
"""Create the ELB"""
if
not
self
.
elb
:
# Zones and listeners will be added at creation
self
.
_create_elb
()
else
:
self
.
_set_zones
()
self
.
_set_security_groups
()
self
.
_set_elb_listeners
()
self
.
_set_subnets
()
self
.
_set_health_check
()
self
.
do_tags
()
def
ensure_gone
(
self
):
"""Destroy the ELB"""
if
self
.
elb
:
self
.
_delete_elb
()
def
get_info
(
self
):
try
:
check_elb
=
self
.
elb_conn
.
get_all_load_balancers
(
self
.
name
)[
0
]
except
:
check_elb
=
None
if
not
check_elb
:
info
=
{
'name'
:
self
.
name
,
'status'
:
self
.
status
}
else
:
info
=
{
'name'
:
check_elb
.
name
,
'dns_name'
:
check_elb
.
dns_name
,
'zones'
:
check_elb
.
availability_zones
,
'security_group_ids'
:
check_elb
.
security_groups
,
'status'
:
self
.
status
,
'subnets'
:
self
.
subnets
,
'scheme'
:
check_elb
.
scheme
}
if
check_elb
.
health_check
:
info
[
'health_check'
]
=
{
'target'
:
check_elb
.
health_check
.
target
,
'interval'
:
check_elb
.
health_check
.
interval
,
'timeout'
:
check_elb
.
health_check
.
timeout
,
'healthy_threshold'
:
check_elb
.
health_check
.
healthy_threshold
,
'unhealthy_threshold'
:
check_elb
.
health_check
.
unhealthy_threshold
,
}
if
check_elb
.
listeners
:
info
[
'listeners'
]
=
[
l
.
get_complex_tuple
()
for
l
in
check_elb
.
listeners
]
elif
self
.
status
==
'created'
:
# When creating a new ELB, listeners don't show in the
# immediately returned result, so just include the
# ones that were added
info
[
'listeners'
]
=
[
self
.
_listener_as_tuple
(
l
)
for
l
in
self
.
listeners
]
else
:
info
[
'listeners'
]
=
[]
return
info
def
_get_elb
(
self
):
elbs
=
self
.
elb_conn
.
get_all_load_balancers
()
for
elb
in
elbs
:
if
self
.
name
==
elb
.
name
:
self
.
status
=
'ok'
return
elb
def
_get_elb_connection
(
self
):
try
:
return
connect_to_aws
(
boto
.
ec2
.
elb
,
self
.
region
,
**
self
.
aws_connect_params
)
except
boto
.
exception
.
NoAuthHandlerFound
,
e
:
self
.
module
.
fail_json
(
msg
=
str
(
e
))
def
_delete_elb
(
self
):
# True if succeeds, exception raised if not
result
=
self
.
elb_conn
.
delete_load_balancer
(
name
=
self
.
name
)
if
result
:
self
.
changed
=
True
self
.
status
=
'deleted'
def
_create_elb
(
self
):
listeners
=
[
self
.
_listener_as_tuple
(
l
)
for
l
in
self
.
listeners
]
self
.
elb
=
self
.
elb_conn
.
create_load_balancer
(
name
=
self
.
name
,
zones
=
self
.
zones
,
security_groups
=
self
.
security_group_ids
,
complex_listeners
=
listeners
,
subnets
=
self
.
subnets
,
scheme
=
self
.
scheme
)
if
self
.
elb
:
self
.
changed
=
True
self
.
status
=
'created'
def
_create_elb_listeners
(
self
,
listeners
):
"""Takes a list of listener tuples and creates them"""
# True if succeeds, exception raised if not
self
.
changed
=
self
.
elb_conn
.
create_load_balancer_listeners
(
self
.
name
,
complex_listeners
=
listeners
)
def
_delete_elb_listeners
(
self
,
listeners
):
"""Takes a list of listener tuples and deletes them from the elb"""
ports
=
[
l
[
0
]
for
l
in
listeners
]
# True if succeeds, exception raised if not
self
.
changed
=
self
.
elb_conn
.
delete_load_balancer_listeners
(
self
.
name
,
ports
)
def
_set_elb_listeners
(
self
):
"""
Creates listeners specified by self.listeners; overwrites existing
listeners on these ports; removes extraneous listeners
"""
listeners_to_add
=
[]
listeners_to_remove
=
[]
listeners_to_keep
=
[]
# Check for any listeners we need to create or overwrite
for
listener
in
self
.
listeners
:
listener_as_tuple
=
self
.
_listener_as_tuple
(
listener
)
# First we loop through existing listeners to see if one is
# already specified for this port
existing_listener_found
=
None
for
existing_listener
in
self
.
elb
.
listeners
:
# Since ELB allows only one listener on each incoming port, a
# single match on the incomping port is all we're looking for
if
existing_listener
[
0
]
==
listener
[
'load_balancer_port'
]:
existing_listener_found
=
existing_listener
.
get_complex_tuple
()
break
if
existing_listener_found
:
# Does it match exactly?
if
listener_as_tuple
!=
existing_listener_found
:
# The ports are the same but something else is different,
# so we'll remove the exsiting one and add the new one
listeners_to_remove
.
append
(
existing_listener_found
)
listeners_to_add
.
append
(
listener_as_tuple
)
else
:
# We already have this listener, so we're going to keep it
listeners_to_keep
.
append
(
existing_listener_found
)
else
:
# We didn't find an existing listener, so just add the new one
listeners_to_add
.
append
(
listener_as_tuple
)
# Check for any extraneous listeners we need to remove, if desired
if
self
.
purge_listeners
:
for
existing_listener
in
self
.
elb
.
listeners
:
existing_listener_tuple
=
existing_listener
.
get_complex_tuple
()
if
existing_listener_tuple
in
listeners_to_remove
:
# Already queued for removal
continue
if
existing_listener_tuple
in
listeners_to_keep
:
# Keep this one around
continue
# Since we're not already removing it and we don't need to keep
# it, let's get rid of it
listeners_to_remove
.
append
(
existing_listener_tuple
)
if
listeners_to_remove
:
self
.
_delete_elb_listeners
(
listeners_to_remove
)
if
listeners_to_add
:
self
.
_create_elb_listeners
(
listeners_to_add
)
def
_listener_as_tuple
(
self
,
listener
):
"""Formats listener as a 4- or 5-tuples, in the order specified by the
ELB API"""
# N.B. string manipulations on protocols below (str(), upper()) is to
# ensure format matches output from ELB API
listener_list
=
[
listener
[
'load_balancer_port'
],
listener
[
'instance_port'
],
str
(
listener
[
'protocol'
]
.
upper
()),
]
# Instance protocol is not required by ELB API; it defaults to match
# load balancer protocol. We'll mimic that behavior here
if
'instance_protocol'
in
listener
:
listener_list
.
append
(
str
(
listener
[
'instance_protocol'
]
.
upper
()))
else
:
listener_list
.
append
(
str
(
listener
[
'protocol'
]
.
upper
()))
if
'ssl_certificate_id'
in
listener
:
listener_list
.
append
(
str
(
listener
[
'ssl_certificate_id'
]))
return
tuple
(
listener_list
)
def
_enable_zones
(
self
,
zones
):
try
:
self
.
elb
.
enable_zones
(
zones
)
except
boto
.
exception
.
BotoServerError
,
e
:
if
"Invalid Availability Zone"
in
e
.
error_message
:
self
.
module
.
fail_json
(
msg
=
e
.
error_message
)
else
:
self
.
module
.
fail_json
(
msg
=
"an unknown server error occurred, please try again later"
)
self
.
changed
=
True
def
_disable_zones
(
self
,
zones
):
try
:
self
.
elb
.
disable_zones
(
zones
)
except
boto
.
exception
.
BotoServerError
,
e
:
if
"Invalid Availability Zone"
in
e
.
error_message
:
self
.
module
.
fail_json
(
msg
=
e
.
error_message
)
else
:
self
.
module
.
fail_json
(
msg
=
"an unknown server error occurred, please try again later"
)
self
.
changed
=
True
def
_attach_subnets
(
self
,
subnets
):
self
.
elb_conn
.
attach_lb_to_subnets
(
self
.
name
,
subnets
)
self
.
changed
=
True
def
_detach_subnets
(
self
,
subnets
):
self
.
elb_conn
.
detach_lb_from_subnets
(
self
.
name
,
subnets
)
self
.
changed
=
True
def
_set_subnets
(
self
):
"""Determine which subnets need to be attached or detached on the ELB"""
if
self
.
subnets
:
if
self
.
purge_subnets
:
subnets_to_detach
=
list
(
set
(
self
.
elb
.
subnets
)
-
set
(
self
.
subnets
))
subnets_to_attach
=
list
(
set
(
self
.
subnets
)
-
set
(
self
.
elb
.
subnets
))
else
:
subnets_to_detach
=
None
subnets_to_attach
=
list
(
set
(
self
.
subnets
)
-
set
(
self
.
elb
.
subnets
))
if
subnets_to_attach
:
self
.
_attach_subnets
(
subnets_to_attach
)
if
subnets_to_detach
:
self
.
_detach_subnets
(
subnets_to_detach
)
def
_set_zones
(
self
):
"""Determine which zones need to be enabled or disabled on the ELB"""
if
self
.
zones
:
if
self
.
purge_zones
:
zones_to_disable
=
list
(
set
(
self
.
elb
.
availability_zones
)
-
set
(
self
.
zones
))
zones_to_enable
=
list
(
set
(
self
.
zones
)
-
set
(
self
.
elb
.
availability_zones
))
else
:
zones_to_disable
=
None
zones_to_enable
=
list
(
set
(
self
.
zones
)
-
set
(
self
.
elb
.
availability_zones
))
if
zones_to_enable
:
self
.
_enable_zones
(
zones_to_enable
)
# N.B. This must come second, in case it would have removed all zones
if
zones_to_disable
:
self
.
_disable_zones
(
zones_to_disable
)
def
_set_security_groups
(
self
):
if
self
.
security_group_ids
!=
None
and
set
(
self
.
elb
.
security_groups
)
!=
set
(
self
.
security_group_ids
):
self
.
elb_conn
.
apply_security_groups_to_lb
(
self
.
name
,
self
.
security_group_ids
)
self
.
Changed
=
True
def
_set_health_check
(
self
):
"""Set health check values on ELB as needed"""
if
self
.
health_check
:
# This just makes it easier to compare each of the attributes
# and look for changes. Keys are attributes of the current
# health_check; values are desired values of new health_check
health_check_config
=
{
"target"
:
self
.
_get_health_check_target
(),
"timeout"
:
self
.
health_check
[
'response_timeout'
],
"interval"
:
self
.
health_check
[
'interval'
],
"unhealthy_threshold"
:
self
.
health_check
[
'unhealthy_threshold'
],
"healthy_threshold"
:
self
.
health_check
[
'healthy_threshold'
],
}
update_health_check
=
False
# The health_check attribute is *not* set on newly created
# ELBs! So we have to create our own.
if
not
self
.
elb
.
health_check
:
self
.
elb
.
health_check
=
HealthCheck
()
for
attr
,
desired_value
in
health_check_config
.
iteritems
():
if
getattr
(
self
.
elb
.
health_check
,
attr
)
!=
desired_value
:
setattr
(
self
.
elb
.
health_check
,
attr
,
desired_value
)
update_health_check
=
True
if
update_health_check
:
self
.
elb
.
configure_health_check
(
self
.
elb
.
health_check
)
self
.
changed
=
True
def
_get_health_check_target
(
self
):
"""Compose target string from healthcheck parameters"""
protocol
=
self
.
health_check
[
'ping_protocol'
]
.
upper
()
path
=
""
if
protocol
in
[
'HTTP'
,
'HTTPS'
]
and
'ping_path'
in
self
.
health_check
:
path
=
self
.
health_check
[
'ping_path'
]
return
"
%
s:
%
s
%
s"
%
(
protocol
,
self
.
health_check
[
'ping_port'
],
path
)
## can be removed if https://github.com/ansible/ansible/pull/9113 is merged upstream
def
is_taggable
(
self
,
object
):
from
boto.ec2.ec2object
import
TaggedEC2Object
if
not
object
or
not
issubclass
(
object
.
__class__
,
TaggedEC2Object
):
return
False
return
True
def
do_tags
(
self
):
"""
General function for adding tags to objects that are subclasses
of boto.ec2.ec2object.TaggedEC2Object. Currently updates
existing tags, as the API overwrites them, but does not remove
orphans.
:param module:
:param object:
:param tags:
"""
dry_run
=
True
if
self
.
module
.
check_mode
else
False
if
(
self
.
is_taggable
(
self
.
elb
)):
tag_dict
=
{}
for
tag
in
self
.
tags
:
tag_dict
[
tag
[
'key'
]]
=
tag
[
'value'
]
self
.
elb
.
add_tags
(
tag_dict
,
dry_run
)
else
:
pass
#self.module.fail_json(msg="ELB object is not a subclass of TaggedEC2Object")
## end can be removed
def
main
():
argument_spec
=
ec2_argument_spec
()
argument_spec
.
update
(
dict
(
state
=
{
'required'
:
True
,
'choices'
:
[
'present'
,
'absent'
]},
name
=
{
'required'
:
True
},
listeners
=
{
'default'
:
None
,
'required'
:
False
,
'type'
:
'list'
},
purge_listeners
=
{
'default'
:
True
,
'required'
:
False
,
'type'
:
'bool'
},
zones
=
{
'default'
:
None
,
'required'
:
False
,
'type'
:
'list'
},
purge_zones
=
{
'default'
:
False
,
'required'
:
False
,
'type'
:
'bool'
},
security_group_ids
=
{
'default'
:
None
,
'required'
:
False
,
'type'
:
'list'
},
health_check
=
{
'default'
:
None
,
'required'
:
False
,
'type'
:
'dict'
},
subnets
=
{
'default'
:
None
,
'required'
:
False
,
'type'
:
'list'
},
purge_subnets
=
{
'default'
:
False
,
'required'
:
False
,
'type'
:
'bool'
},
scheme
=
{
'default'
:
'internet-facing'
,
'required'
:
False
},
tags
=
{
'default'
:
None
,
'required'
:
False
,
'type'
:
'list'
}
)
)
module
=
AnsibleModule
(
argument_spec
=
argument_spec
,
)
region
,
ec2_url
,
aws_connect_params
=
get_aws_connection_info
(
module
)
if
not
region
:
module
.
fail_json
(
msg
=
"Region must be specified as a parameter, in EC2_REGION or AWS_REGION environment variables or in boto configuration file"
)
name
=
module
.
params
[
'name'
]
state
=
module
.
params
[
'state'
]
listeners
=
module
.
params
[
'listeners'
]
purge_listeners
=
module
.
params
[
'purge_listeners'
]
zones
=
module
.
params
[
'zones'
]
purge_zones
=
module
.
params
[
'purge_zones'
]
security_group_ids
=
module
.
params
[
'security_group_ids'
]
health_check
=
module
.
params
[
'health_check'
]
subnets
=
module
.
params
[
'subnets'
]
purge_subnets
=
module
.
params
[
'purge_subnets'
]
scheme
=
module
.
params
[
'scheme'
]
tags
=
module
.
params
[
'tags'
]
if
state
==
'present'
and
not
listeners
:
module
.
fail_json
(
msg
=
"At least one port is required for ELB creation"
)
if
state
==
'present'
and
not
(
zones
or
subnets
):
module
.
fail_json
(
msg
=
"At least one availability zone or subnet is required for ELB creation"
)
elb_man
=
ElbManager
(
module
,
name
,
listeners
,
purge_listeners
,
zones
,
purge_zones
,
security_group_ids
,
health_check
,
subnets
,
purge_subnets
,
scheme
,
tags
,
region
=
region
,
**
aws_connect_params
)
if
state
==
'present'
:
elb_man
.
ensure_ok
()
elif
state
==
'absent'
:
elb_man
.
ensure_gone
()
ansible_facts
=
{
'ec2_elb'
:
'info'
}
ec2_facts_result
=
dict
(
changed
=
elb_man
.
changed
,
elb
=
elb_man
.
get_info
(),
ansible_facts
=
ansible_facts
)
module
.
exit_json
(
**
ec2_facts_result
)
# import module snippets
from
ansible.module_utils.basic
import
*
from
ansible.module_utils.ec2
import
*
main
()
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment