def update_vpgw_associations(self): remote = set(r['GatewayId'] for r in self.object.get("PropagatingsVgws", [])) local = set() for vgw in self.resource.propagating_vpn_gateways: id = self.runner.get_plan(vgw).resource_id if not id or id not in remote: yield self.generic_action( "Enable route propagation from vpn gateway {}".format( vgw.name), self.client.enable_vgw_route_propagation, RouteTableId=serializers.Identifier(), GatewayId=serializers.Identifier( inner=serializers.Const(vgw)), ) if id: local.add(id) for vgw in remote.difference(local): yield self.generic_action( "Disable route propagation from vpn gateway {}".format(vgw), self.client.disable_vgw_route_propagation, RouteTableId=serializers.Identifier(), GatewayId=serializers.Const(inner=serializers.Const(vgw)), )
def update_object(self): for local_rule in self.resource.ingress: for remote_rule in self.object.get("IpPermissions", []): if local_rule.matches(self.runner, remote_rule): break else: yield self.generic_action( "Authorize ingress {}".format(local_rule), self.client.authorize_security_group_ingress, GroupId=serializers.Identifier(), IpPermissions=serializers.ListOfOne( serializers.Context(serializers.Const(local_rule), serializers.Resource())), ) return for local_rule in self.resource.egress: for remote_rule in self.object.get("IpPermissionsEgress", []): if local_rule.matches(self.runner, remote_rule): break else: yield self.generic_action( "Authorize egress {}".format(local_rule), self.client.authorize_security_group_egress, GroupId=serializers.Identifier(), IpPermissions=serializers.ListOfOne( serializers.Context(serializers.Const(local_rule), serializers.Resource())), )
def update_attributes(self): if not self.resource.attributes: return a = self.resource.attributes changed = False if not self.object: changed = True else: attributes = self.client.describe_load_balancer_attributes( LoadBalancerName=self.resource_id)['LoadBalancerAttributes'] if attributes['ConnectionSettings'][ 'IdleTimeout'] != a.idle_timeout: changed = True if attributes['ConnectionDraining'][ 'Timeout'] != a.connection_draining: changed = True if attributes['CrossZoneLoadBalancing'][ 'Enabled'] != a.cross_zone_load_balancing: changed = True if attributes['AccessLog'].get('S3BucketName', None) != a.access_log: changed = True if changed: yield self.generic_action( "Configure attributes", self.client.modify_load_balancer_attributes, LoadBalancerName=serializers.Identifier(), LoadBalancerAttributes=serializers.Context( serializers.Const(a), serializers.Resource()), )
def update_health_check(self): if not self.object and self.resource.health_check: yield self.generic_action( "Configure health check", self.client.configure_health_check, LoadBalancerName=self.resource.name, HealthCheck=serializers.Context( serializers.Const(self.resource.health_check), serializers.Resource(), ), )
def get_serializer(self, runner): return serializers.Context( serializers.Const(self.adapts), serializers.Dict( DNSName=serializers.Context( serializers.Property("CanonicalHostedZoneName"), serializers.Expression(lambda r, o: route53._normalize(o)), ), HostedZoneId=serializers.Property("CanonicalHostedZoneNameID"), EvaluateTargetHealth=False, ))
def get_serializer(self, runner): plan = runner.get_plan(self.adapts) # Annoyingly we have to get antother client (different API) to get info # on teh EC2 instances in our asg client = plan.session.create_client( service_name="ec2", region_name=plan.session.region, aws_access_key_id=plan.session.access_key_id, aws_secret_access_key=plan.session.secret_access_key, aws_session_token=plan.session.session_token, ) reservations = client.describe_instances(InstanceIds=[ i["InstanceId"] for i in plan.object.get("Instances", []) ], ).get("Reservations", []) instances = [] for reservation in reservations: instances.extend(reservation.get("Instances", [])) if len(instances) == 0: raise errors.Error("No instances available in {}".format( self.adapts)) if hasattr( self.parent, "proxy" ) and self.parent.proxy and self.parent.proxy.instance and self.parent.proxy.instance.adapts.subnets[ 0].vpc == self.adapts.subnets[0].vpc: for instance in instances: if 'PrivateIpAddress' in instance: return serializers.Const(instance['PrivateIpAddress']) for instance in instances: for k in ('PublicDnsName', 'PublicIpAddress'): if k in instance and instance[k]: return serializers.Const(instance[k]) raise errors.Error( "No instances available in {} with ip address".format(self.adapts))
def update_routes(self): """ Compare the individual routes listed in the RouteTable to the ones defined in the current workspace, creating and removing routes as needed. Old routes are removed *before* new routes are added. This may cause connection glitches when applied, but it avoids route collisions. """ remote_routes = list(d for d in self.object.get("Routes", []) if d["GatewayId"] != "local") if remote_routes: for remote in remote_routes: for local in self.resource.routes: if local.matches(self.runner, remote): break else: yield self.generic_action( "Remove route for {}".format( remote['DestinationCidrBlock']), self.client.delete_route, RouteTableId=serializers.Identifier(), DestinationCidrBlock=remote['DestinationCidrBlock'], ) if self.resource.routes: for local in self.resource.routes: for remote in remote_routes: if local.matches(self.runner, remote): break else: yield self.generic_action( "Adding route for {}".format(local.destination_cidr), self.client.create_route, serializers.Context( serializers.Const(local), serializers.Resource( RouteTableId=serializers.Identifier( serializers.Const(self.resource)), )))
def __init__(self, plan, description, func, serializer=None, **kwargs): super(GenericAction, self).__init__(plan) self.func = func self._description = description if serializer: self.serializer = serializer else: self.serializer = serializers.Dict( **{ k: v if isinstance(v, serializers.Serializer ) else serializers.Const(v) for (k, v) in kwargs.items() })
class DefaultCacheBehavior(Resource): resource_name = "default_cache_behaviour" dot_ignore = True extra_serializers = { # TrustedSigners are not supported yet, so include stub in serialized form "TrustedSigners": serializers.Const({ "Enabled": False, "Quantity": 0, }), "AllowedMethods": CloudFrontList( inner=serializers.Context(serializers.Argument("allowed_methods"), serializers.List()), CachedMethods=serializers.Context( serializers.Argument("cached_methods"), CloudFrontList()), ), } target_origin = argument.String(field='TargetOriginId') forwarded_values = argument.Resource( ForwardedValues, default=lambda instance: dict(), field="ForwardedValues", serializer=serializers.Resource(), ) viewer_protocol_policy = argument.String( choices=['allow-all', 'https-only', 'redirect-to-https'], default='allow-all', field="ViewerProtocolPolicy") min_ttl = argument.Integer(default=0, field="MinTTL") allowed_methods = argument.List(default=lambda x: ["GET", "HEAD"]) cached_methods = argument.List(default=lambda x: ["GET", "HEAD"]) smooth_streaming = argument.Boolean(default=False, field='SmoothStreaming')
def test_string(self): serializer = serializers.String(serializers.Const(1)) result = serializer.render(self.runner, self.resource) self.assertEqual(result, "1")
def test_boolean(self): serializer = serializers.Boolean(serializers.Const(1)) result = serializer.render(self.runner, self.resource) self.assertEqual(result, True)
def test_const(self): serializer = serializers.Const("FOO") self.assertEqual(serializer.render(self.runner, None), "FOO")
def get_property(self, name): return Property(name, serializers.Const(self))
class Distribution(Resource): resource_name = "distribution" extra_serializers = { "CallerReference": serializers.Expression(lambda runner, object: runner.get_plan(object). object.get('DistributionConfig', {}).get( 'CallerReference', str(uuid.uuid4()))), "Aliases": CloudFrontList( serializers.Chain( serializers.Context(serializers.Argument("name"), serializers.ListOfOne()), serializers.Context(serializers.Argument("aliases"), serializers.List()), )), # We don't support GeoRestrictions yet - so include a stubbed default # when serializing "Restrictions": serializers.Const({ "GeoRestriction": { "RestrictionType": "none", "Quantity": 0, }, }), } name = argument.String() comment = argument.String(field='Comment', default=lambda instance: instance.name) aliases = argument.List() root_object = argument.String(default='/', field="DefaultRootObject") enabled = argument.Boolean(default=True, field="Enabled") origins = argument.ResourceList( (S3Origin, CustomOrigin), field="Origins", serializer=CloudFrontResourceList(), ) default_cache_behavior = argument.Resource( DefaultCacheBehavior, field="DefaultCacheBehavior", serializer=serializers.Resource(), ) behaviors = argument.ResourceList( CacheBehavior, field="CacheBehaviors", serializer=CloudFrontResourceList(), ) error_responses = argument.ResourceList( ErrorResponse, field="CustomErrorResponses", serializer=CloudFrontResourceList(), ) logging = argument.Resource( LoggingConfig, default=lambda instance: dict(enabled=False), field="Logging", serializer=serializers.Resource(), ) price_class = argument.String( default="PriceClass_100", choices=['PriceClass_100', 'PriceClass_200', 'PriceClass_All'], field="PriceClass", ) viewer_certificate = argument.Resource( ViewerCertificate, field="ViewerCertificate", serializer=serializers.Resource(), ) account = argument.Resource(Account)
def test_integer(self): serializer = serializers.Integer(serializers.Const("1")) result = serializer.render(self.runner, self.resource) self.assertEqual(result, 1)
def get_create_serializer(self): # As the create call takes *0* parameters, the serializers consider it # a "FieldNotPresent" and break out. return serializers.Const({})
def update_object(self): changes = [] description = ["Update hosted zone records"] # Retrieve all DNS records associated with this hosted zone # Ignore SOA and NS records for the top level domain remote_records = [] if self.resource_id: for record in self.client.list_resource_record_sets( HostedZoneId=self.resource_id)['ResourceRecordSets']: if record['Type'] in ( 'SOA', 'NS') and record['Name'] == self.resource.name: continue remote_records.append(record) for local in self.resource.records: for remote in remote_records: if local.matches(self.runner, remote): break else: changes.append( serializers.Dict( Action="UPSERT", ResourceRecordSet=serializers.Context( serializers.Const(local), serializers.Resource()), )) description.append("Name => {}, Type={}, Action=UPSERT".format( local.name, local.type)) if not self.resource.shared: for remote in remote_records: for local in self.resource.records: if remote["Name"] != local.name: continue if remote["Type"] != local.type: continue if remote.get("SetIdentifier", None) != local.set_identifier: continue break else: changes.append( serializers.Const({ "Action": "DELETE", "ResourceRecordSet": record })) description.append( "Name => {}, Type={}, Action=DELETE".format( record["Name"], record["Type"])) if changes: yield self.generic_action( description, self.client.change_resource_record_sets, serializers.Dict( HostedZoneId=serializers.Identifier(), ChangeBatch=serializers.Dict( #Comment="", Changes=serializers.Context( serializers.Const(changes), serializers.List(serializers.SubSerializer())), )), )