Permalink
Browse files

Merge branch 'release-2.18.0'

  • Loading branch information...
2 parents 0172b41 + cb76bf8 commit bc48be4b533357c741f223683095e576f3d9ef0c @danielgtaylor danielgtaylor committed Nov 22, 2013
View
@@ -1,9 +1,9 @@
####
boto
####
-boto 2.17.0
+boto 2.18.0
-Released: 14-November-2013
+Released: 22-November-2013
.. image:: https://travis-ci.org/boto/boto.png?branch=develop
:target: https://travis-ci.org/boto/boto
View
@@ -36,7 +36,7 @@
import urlparse
from boto.exception import InvalidUriError
-__version__ = '2.17.0'
+__version__ = '2.18.0'
Version = __version__ # for backware compatibility
UserAgent = 'Boto/%s Python/%s %s/%s' % (
View
@@ -245,14 +245,6 @@ def create_environment(self, application_name, environment_name,
version to be deployed. If no application is found with this name,
CreateEnvironment returns an InvalidParameterValue error.
- :type version_label: string
- :param version_label: The name of the application version to deploy. If
- the specified application has no associated application versions,
- AWS Elastic Beanstalk UpdateEnvironment returns an
- InvalidParameterValue error. Default: If not specified, AWS
- Elastic Beanstalk attempts to launch the most recently created
- application version.
-
:type environment_name: string
:param environment_name: A unique name for the deployment environment.
Used in the application URL. Constraint: Must be from 4 to 23
@@ -264,6 +256,14 @@ def create_environment(self, application_name, environment_name,
name becomes part of the CNAME, and therefore part of the visible
URL for your application.
+ :type version_label: string
+ :param version_label: The name of the application version to deploy. If
+ the specified application has no associated application versions,
+ AWS Elastic Beanstalk UpdateEnvironment returns an
+ InvalidParameterValue error. Default: If not specified, AWS
+ Elastic Beanstalk attempts to launch the most recently created
+ application version.
+
:type template_name: string
:param template_name: The name of the configuration template to
use in deployment. If no configuration template is found with this
@@ -128,7 +128,7 @@ def create_trail(self, trail=None):
**TrailAlreadyExists**
- At attempt was made to create a trail with a name that already
+ An attempt was made to create a trail with a name that already
exists.
**S3BucketDoesNotExist**
@@ -138,7 +138,7 @@ def create_trail(self, trail=None):
**InsufficientS3BucketPolicy**
Policy on Amazon S3 bucket does not permit CloudTrail to write
- to your bucket. See the AWS AWS CloudTrail User Guide for the
+ to your bucket. See the AWS CloudTrail User Guide for the
required bucket policy.
**InsufficientSnsTopicPolicy**
View
@@ -372,7 +372,8 @@ def authorize(self, connection, **kwargs):
for key in self.headers:
val = self.headers[key]
if isinstance(val, unicode):
- self.headers[key] = urllib.quote_plus(val.encode('utf-8'))
+ safe = '!"#$%&\'()*+,/:;<=>?@[\\]^`{|}~'
+ self.headers[key] = urllib.quote_plus(val.encode('utf-8'), safe)
connection._auth_handler.add_auth(self, **kwargs)
@@ -117,7 +117,7 @@ def __init__(self, aws_access_key_id=None, aws_secret_access_key=None,
validate_certs=validate_certs)
def _required_auth_capability(self):
- return ['ec2']
+ return ['hmac-v4']
def build_dimension_param(self, dimension, params):
prefix = 'Dimensions.member'
View
@@ -62,6 +62,7 @@
from boto.ec2.volumestatus import VolumeStatusSet
from boto.ec2.networkinterface import NetworkInterface
from boto.ec2.attributes import AccountAttribute, VPCAttribute
+from boto.ec2.blockdevicemapping import BlockDeviceMapping, BlockDeviceType
from boto.exception import EC2ResponseError
#boto.set_stream_logger('ec2')
@@ -260,7 +261,8 @@ def get_image(self, image_id, dry_run=False):
def register_image(self, name=None, description=None, image_location=None,
architecture=None, kernel_id=None, ramdisk_id=None,
root_device_name=None, block_device_map=None,
- dry_run=False, virtualization_type=None):
+ dry_run=False, virtualization_type=None,
+ snapshot_id=None):
"""
Register an image.
@@ -299,6 +301,11 @@ def register_image(self, name=None, description=None, image_location=None,
* paravirtual
* hvm
+ :type snapshot_id: string
+ :param snapshot_id: A snapshot ID for the snapshot to be used
+ as root device for the image. Mutually exclusive with
+ block_device_map, requires root_device_name
+
:rtype: string
:return: The new image id
"""
@@ -317,12 +324,17 @@ def register_image(self, name=None, description=None, image_location=None,
params['ImageLocation'] = image_location
if root_device_name:
params['RootDeviceName'] = root_device_name
+ if snapshot_id:
+ root_vol = BlockDeviceType(snapshot_id=snapshot_id)
+ block_device_map = BlockDeviceMapping()
+ block_device_map[root_device_name] = root_vol
if block_device_map:
block_device_map.ec2_build_list_params(params)
if dry_run:
params['DryRun'] = 'true'
if virtualization_type:
params['VirtualizationType'] = virtualization_type
+
rs = self.get_object('RegisterImage', params, ResultSet, verb='POST')
image_id = getattr(rs, 'imageId', None)
View
@@ -390,6 +390,76 @@ def disable_availability_zones(self, load_balancer_name, zones_to_remove):
params, LoadBalancerZones)
return obj.zones
+ def modify_lb_attribute(self, load_balancer_name, attribute, value):
+ """Changes an attribute of a Load Balancer
+
+ :type load_balancer_name: string
+ :param load_balancer_name: The name of the Load Balancer
+
+ :type attribute: string
+ :param attribute: The attribute you wish to change.
+
+ * crossZoneLoadBalancing - Boolean (true)
+
+ :type value: string
+ :param value: The new value for the attribute
+
+ :rtype: bool
+ :return: Whether the operation succeeded or not
+ """
+
+ bool_reqs = ('crosszoneloadbalancing',)
+ if attribute.lower() in bool_reqs:
+ if isinstance(value, bool):
+ if value:
+ value = 'true'
+ else:
+ value = 'false'
+
+ params = {'LoadBalancerName': load_balancer_name}
+ if attribute.lower() == 'crosszoneloadbalancing':
+ params['LoadBalancerAttributes.CrossZoneLoadBalancing.Enabled'
+ ] = value
+ else:
+ raise ValueError('InvalidAttribute', attribute)
+ return self.get_status('ModifyLoadBalancerAttributes', params,
+ verb='GET')
+
+ def get_all_lb_attributes(self, load_balancer_name):
+ """Gets all Attributes of a Load Balancer
+
+ :type load_balancer_name: string
+ :param load_balancer_name: The name of the Load Balancer
+
+ :rtype: boto.ec2.elb.attribute.LbAttributes
+ :return: The attribute object of the ELB.
+ """
+ from boto.ec2.elb.attributes import LbAttributes
+ params = {'LoadBalancerName': load_balancer_name}
+ return self.get_object('DescribeLoadBalancerAttributes',
+ params, LbAttributes)
+
+ def get_lb_attribute(self, load_balancer_name, attribute):
+ """Gets an attribute of a Load Balancer
+
+ This will make an EC2 call for each method call.
+
+ :type load_balancer_name: string
+ :param load_balancer_name: The name of the Load Balancer
+
+ :type attribute: string
+ :param attribute: The attribute you wish to see.
+
+ * crossZoneLoadBalancing - Boolean
+
+ :rtype: Attribute dependent
+ :return: The new value for the attribute
+ """
+ attributes = self.get_all_lb_attributes(load_balancer_name)
+ if attribute.lower() == 'crosszoneloadbalancing':
+ return attributes.cross_zone_load_balancing.enabled
+ return None
+
def register_instances(self, load_balancer_name, instances):
"""
Add new Instances to an existing Load Balancer.
View
@@ -0,0 +1,61 @@
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+# Created by Chris Huegle for TellApart, Inc.
+
+class CrossZoneLoadBalancingAttribute(object):
+ """
+ Represents the CrossZoneLoadBalancing segement of ELB Attributes.
+ """
+ def __init__(self, connection=None):
+ self.enabled = None
+
+ def __repr__(self):
+ return 'CrossZoneLoadBalancingAttribute(%s)' % (
+ self.enabled)
+
+ def startElement(self, name, attrs, connection):
+ pass
+
+ def endElement(self, name, value, connection):
+ if name == 'Enabled':
+ if value.lower() == 'true':
+ self.enabled = True
+ else:
+ self.enabled = False
+
+class LbAttributes(object):
+ """
+ Represents the Attributes of an Elastic Load Balancer.
+ """
+ def __init__(self, connection=None):
+ self.connection = connection
+ self.cross_zone_load_balancing = CrossZoneLoadBalancingAttribute(
+ self.connection)
+
+ def __repr__(self):
+ return 'LbAttributes(%s)' % (
+ repr(self.cross_zone_load_balancing))
+
+ def startElement(self, name, attrs, connection):
+ if name == 'CrossZoneLoadBalancing':
+ return self.cross_zone_load_balancing
+
+ def endElement(self, name, value, connection):
+ pass
@@ -122,6 +122,7 @@ def __init__(self, connection=None, name=None, endpoints=None):
self.vpc_id = None
self.scheme = None
self.backends = None
+ self._attributes = None
def __repr__(self):
return 'LoadBalancer:%s' % self.name
@@ -203,6 +204,58 @@ def disable_zones(self, zones):
new_zones = self.connection.disable_availability_zones(self.name, zones)
self.availability_zones = new_zones
+ def get_attributes(self, force=False):
+ """
+ Gets the LbAttributes. The Attributes will be cached.
+
+ :type force: bool
+ :param force: Ignore cache value and reload.
+
+ :rtype: boto.ec2.elb.attributes.LbAttributes
+ :return: The LbAttribues object
+ """
+ if not self._attributes or force:
+ self._attributes = self.connection.get_all_lb_attributes(self.name)
+ return self._attributes
+
+ def is_cross_zone_load_balancing(self, force=False):
+ """
+ Identifies if the ELB is current configured to do CrossZone Balancing.
+
+ :type force: bool
+ :param force: Ignore cache value and reload.
+
+ :rtype: bool
+ :return: True if balancing is enabled, False if not.
+ """
+ return self.get_attributes(force).cross_zone_load_balancing.enabled
+
+ def enable_cross_zone_load_balancing(self):
+ """
+ Turns on CrossZone Load Balancing for this ELB.
+
+ :rtype: bool
+ :return: True if successful, False if not.
+ """
+ success = self.connection.modify_lb_attribute(
+ self.name, 'crossZoneLoadBalancing', True)
+ if success and self._attributes:
+ self._attributes.cross_zone_load_balancing.enabled = True
+ return success
+
+ def disable_cross_zone_load_balancing(self):
+ """
+ Turns off CrossZone Load Balancing for this ELB.
+
+ :rtype: bool
+ :return: True if successful, False if not.
+ """
+ success = self.connection.modify_lb_attribute(
+ self.name, 'crossZoneLoadBalancing', False)
+ if success and self._attributes:
+ self._attributes.cross_zone_load_balancing.enabled = False
+ return success
+
def register_instances(self, instances):
"""
Adds instances to this load balancer. All instances must be in the same
View
@@ -221,6 +221,14 @@ def list_versions(self, prefix='', delimiter='', marker='',
marker, generation_marker,
headers)
+ def validate_get_all_versions_params(self, params):
+ """
+ See documentation in boto/s3/bucket.py.
+ """
+ self.validate_kwarg_names(params,
+ ['version_id_marker', 'delimiter', 'marker',
+ 'generation_marker', 'prefix', 'max_keys'])
+
def delete_key(self, key_name, headers=None, version_id=None,
mfa_token=None, generation=None):
"""
Oops, something went wrong.

0 comments on commit bc48be4

Please sign in to comment.