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())), )
class Connection(resource.Resource): resource_name = "ssh_connection" username = argument.String(default="root", field="username") password = argument.String(field="password") private_key = argument.String(field="pkey", serializer=serializers.Identity()) hostname = argument.String(field="hostname") instance = argument.Resource(Instance, field="hostname", serializer=serializers.Resource()) port = argument.Integer(field="port", default=22) proxy = argument.Resource("touchdown.ssh.Connection") root = argument.Resource(workspace.Workspace) def clean_private_key(self, private_key): if private_key: for cls in (paramiko.RSAKey, paramiko.ECDSAKey, paramiko.DSSKey): try: key = cls.from_private_key(six.BytesIO(private_key)) except paramiko.SSHException: continue return key raise errors.InvalidParameter("Invalid SSH private key")
def _get_local_rules(self): local_rules = {} for i, rule in enumerate(self.resource.inbound, start=1): rule = serializers.Resource().render(self.runner, rule) rule['Protocol'] = self._fix_protocol(rule['Protocol']) rule['RuleNumber'] = i rule['Egress'] = False local_rules[(False, i)] = rule for i, rule in enumerate(self.resource.outbound, start=1): rule = serializers.Resource().render(self.runner, rule) rule['RuleNumber'] = i rule['Protocol'] = self._fix_protocol(rule['Protocol']) rule['Egress'] = True local_rules[(True, i)] = rule return local_rules
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 test_basic_call(self): api = mock.Mock() plan = mock.Mock() plan.resource = CacheCluster(None, name='freddy') g = GenericAction(plan, "I am an action", api, serializer=serializers.Resource()) self.assertEqual(tuple(g.description), ("I am an action", )) g.run() api.assert_called_with(CacheClusterId='freddy', )
def session(self): if not self._session: self.object = self.client.assume_role( **serializers.Resource().render(self.runner, self.resource)) self._session = session.get_session() c = self.object['Credentials'] self._session.access_key_id = c['AccessKeyId'] self._session.secret_access_key = c['SecretAccessKey'] self._session.session_token = c['SessionToken'] self._session.expiration = c['Expiration'] self._session.region = self.resource.account.region return self._session
def test_simple_distribution_with_aliases(self): distribution = Distribution( None, name="example.com", aliases=['www.example.com'], ) result = serializers.Resource().render(mock.Mock(), distribution) del result['CallerReference'] self.assertEqual( result, { 'Origins': { 'Items': [], 'Quantity': 0 }, 'Restrictions': { 'GeoRestriction': { 'RestrictionType': 'none', 'Quantity': 0 } }, 'DefaultRootObject': '/', 'PriceClass': 'PriceClass_100', 'Enabled': True, 'CustomErrorResponses': { 'Items': [], 'Quantity': 0 }, 'CacheBehaviors': { 'Items': [], 'Quantity': 0 }, 'Aliases': { 'Items': ['example.com', 'www.example.com'], 'Quantity': 2 }, 'Logging': { 'Enabled': False, 'Prefix': '', 'Bucket': '', 'IncludeCookies': False }, 'Comment': 'example.com', })
def destroy_object(self): if not self.object: return if self.object['DistributionConfig'].get('Enabled', False): yield self.generic_action( "Disable distribution", self.client.update_distribution, Id=self.object['Id'], IfMatch=self.object['ETag'], DistributionConfig=serializers.Resource(Enabled=False, ), ) yield self.get_waiter( ["Waiting for distribution to enter disabled state"], "distribution_deployed", ) for change in super(Destroy, self).destroy_object(): yield change
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)), )))
class Record(Resource): resource_name = "record" name = argument.String(field="Name") type = argument.String(field="Type") values = argument.List(field="ResourceRecords", serializer=serializers.List(serializers.Dict( Value=serializers.Identity(), ), skip_empty=True)) ttl = argument.Integer(min=0, field="TTL") set_identifier = argument.Integer(min=1, max=128, field="SetIdentifier") alias = argument.Resource( AliasTarget, field="AliasTarget", serializer=serializers.Resource(), ) def clean_name(self, name): return _normalize(name)
class LoadBalancer(Resource): resource_name = "load_balancer" name = argument.String(field="LoadBalancerName") listeners = argument.ResourceList( Listener, field="Listeners", serializer=serializers.List(serializers.Resource()), ) availability_zones = argument.List(field="AvailabilityZones") scheme = argument.String(choices=["internet-facing", "private"], field="Scheme") subnets = argument.ResourceList(Subnet, field="Subnets") security_groups = argument.ResourceList(SecurityGroup, field="SecurityGroups") # tags = argument.Dict() health_check = argument.Resource(HealthCheck) attributes = argument.Resource(Attributes) account = argument.Resource(Account)
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 get_client(self): if self._client: return self._client client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) kwargs = serializers.Resource().render(self.runner, self.resource) if self.resource.proxy: proxy = self.runner.get_plan(self.resource.proxy) transport = proxy.get_client().get_transport() kwargs['sock'] = transport.open_channel( 'direct-tcpip', (kwargs['hostname'], kwargs['port']), ('', 0)) if not self.resource.password and not self.resource.private_key: kwargs['look_for_keys'] = True kwargs['allow_agent'] = True client.connect(**kwargs) self._client = client return client
def update_object(self): if self.update_action and self.object: logger.debug("Checking resource {} for changes".format( self.resource)) description = ["Updating {}".format(self.resource)] local = serializers.Resource(mode="update") for k, v in local.render(self.runner, self.resource).items(): if k not in self.object: continue if v != self.object[k]: logger.debug( "Resource field {} has changed ({} != {})".format( k, v, self.object[k])) description.append("{} => {}".format(k, v)) logger.debug( "Resource has {} differences".format(len(description) - 1)) if len(description) > 1: yield self.generic_action(description, getattr(self.client, self.update_action), serializer=local)
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())), )), )
def get_create_serializer(self): return serializers.Resource()
def get_create_serializer(self): return serializers.Dict(DistributionConfig=serializers.Resource(), )
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 CloudFrontResourceList(): return CloudFrontList(serializers.List(serializers.Resource()))