class UploadServerCertificate(IAMRequest): DESCRIPTION = 'Upload a server certificate' ARGS = [Arg('-s', '--server-certificate-name', metavar='CERTNAME', dest='ServerCertificateName', required=True, help='name to give the new server certificate (required)'), MutuallyExclusiveArgList( Arg('-c', '--certificate-body', dest='CertificateBody', metavar='CERT', help='PEM-encoded certificate'), Arg('--certificate-file', dest='CertificateBody', metavar='FILE', type=open, help='file containing the PEM-encoded certificate')) .required(), MutuallyExclusiveArgList( Arg('--private-key', dest='PrivateKey', metavar='KEY', help='PEM-encoded private key'), Arg('--private-key-file', dest='PrivateKey', metavar='FILE', type=open, help='file containing the PEM-encoded private key')) .required(), MutuallyExclusiveArgList( Arg('--certificate-chain', dest='CertificateChain', metavar='CHAIN', help='''PEM-encoded certificate chain. This is typically the PEM-encoded certificates of the chain, concatenated together.'''), Arg('--certificate-chain-file', dest='CertificateChain', metavar='FILE', help='''file containing the PEM-encoded certificate chain. This is typically the PEM-encoded certificates of the chain, concatenated together.''')), Arg('-p', '--path', dest='Path', help='path for the new server certificate (default: "/")'), AS_ACCOUNT]
class AssociateAddress(EC2Request): DESCRIPTION = 'Associate an elastic IP address with a running instance' ARGS = [Arg('PublicIp', metavar='ADDRESS', nargs='?', help='''[Non-VPC only] IP address to associate (required)'''), Arg('-a', '--allocation-id', dest='AllocationId', metavar='ALLOC', help='[VPC only] VPC allocation ID (required)'), MutuallyExclusiveArgList( Arg('-i', '--instance-id', dest='InstanceId', metavar='INSTANCE', help='''ID of the instance to associate the address with'''), Arg('-n', '--network-interface', dest='NetworkInterfaceId', metavar='INTERFACE', help='''[VPC only] network interface to associate the address with''')) .required(), Arg('-p', '--private-ip-address', dest='PrivateIpAddress', metavar='ADDRESS', help='''[VPC only] the private address to associate with the address being associated in the VPC (default: primary private IP)'''), MutuallyExclusiveArgList( Arg('--allow-reassociation', dest='AllowReassociation', action='store_const', const='true', help='''[VPC only] allow the address to be associated even if it is already associated with another interface'''), Arg('--no-allow-reassociation', dest='AllowReassociation', action='store_const', const='false', help='''[VPC only] do not allow the address to be associated if it is already associated with another interface'''))] # noinspection PyExceptionInherit def configure(self): EC2Request.configure(self) if (self.args.get('PublicIp') is not None and self.args.get('AllocationId') is not None): # Can't be both EC2 and VPC raise ArgumentError( 'argument -a/--allocation-id: not allowed with an IP address') if (self.args.get('PublicIp') is None and self.args.get('AllocationId') is None): # ...but we still have to be one of them raise ArgumentError( 'argument -a/--allocation-id or an IP address is required') if (self.args.get('PublicIp') or '').startswith('eipalloc-'): # Make allocation IDs work positionally for convenience self.params['AllocationId'] = self.params.pop('PublicIp') def print_result(self, result): if self.args.get('AllocationId'): # VPC print self.tabify(('ADDRESS', self.args.get('InstanceId'), self.args.get('AllocationId'), result.get('associationId'), self.args.get('PrivateIpAddress'))) else: # EC2 print self.tabify(('ADDRESS', self.args.get('PublicIp'), self.args.get('InstanceId')))
class UpdateStack(CloudFormationRequest): DESCRIPTION = 'Update a stack with a new template' ARGS = [ Arg('StackName', metavar='STACK', help='name of the stack to update (required)'), MutuallyExclusiveArgList( Arg('--template-file', dest='TemplateBody', metavar='FILE', type=open, help='file containing a new JSON template for the stack'), Arg('--template-url', dest='TemplateURL', metavar='URL', help='URL pointing to a new JSON template for the stack')). required(), Arg('--capabilities', dest='Capabilities.member', metavar='CAP[,...]', type=delimited_list(','), help='capabilities needed to update the stack'), Arg('-p', '--parameter', dest='param_sets', route_to=None, metavar='KEY=VALUE', type=parameter_list, action='append', help='''key and value of the parameters to use with the stack's template, separated by an "=" character'''), MutuallyExclusiveArgList( Arg('--tag', dest='Tags.member', metavar='KEY[=VALUE]', type=binary_tag_def, action='append', help='''key and optional value of a tag to add, separated by an "=" character. If no value is given the tag's value is set to an empty string.'''), Arg('--delete-tags', dest='Tags', action='store_const', const=EMPTY, help='remove all tags associated with the stack')) ] def configure(self): CloudFormationRequest.configure(self) stack_params = sum(self.args.get('param_sets') or [], []) self.params['Parameters.member'] = stack_params # pylint: disable=no-self-use def print_result(self, result): print result.get('StackId')
class MigrateInstances(EC2Request): DESCRIPTION = ('Migrate one instance from its current host, or ' 'migrate all instances from a specific host') ARGS = [ MutuallyExclusiveArgList( Arg('-s', '--source', dest='SourceHost', metavar='HOST', help='remove all instances from a specific host'), Arg('-i', '--instance', dest='InstanceId', metavar='INSTANCE', help='remove one instance from its current host')).required(), MutuallyExclusiveArgList( Arg('--include-dest', action='append', route_to=None, metavar='HOST', help='''allow migration to only a specific host (may be used more than once)'''), Arg('--exclude-dest', action='append', route_to=None, metavar='HOST', help='''allow migration to any host except a specific one (may be used more than once)''')), Arg('--stop-source', action='store_true', route_to=None, help='''also stop the source host to prevent new instances from running on it (requires -s/--source)''') ] def configure(self): EC2Request.configure(self) if self.args.get('stop_source') and not self.args.get('source'): raise ArgumentError('argument --stop-source: only allowed ' 'with -s/--source') def preprocess(self): if self.args.get('include_dest'): self.params['AllowHosts'] = True self.params['DestinationHost'] = self.args['include_dest'] elif self.args.get('exclude_dest'): self.params['AllowHosts'] = False self.params['DestinationHost'] = self.args['exclude_dest'] def postprocess(self, _): req = ModifyService.from_other(self, Name=self.args['source'], State='STOP') req.main()
class GetTemplateSummary(CloudFormationRequest): DESCRIPTION = "Summarize a template" ARGS = [MutuallyExclusiveArgList( Arg('StackName', metavar='STACK', nargs='?', help='''name or ID of the stack (names cannot be used for deleted stacks)'''), Arg('--template-file', dest='TemplateBody', metavar='FILE', type=open, help='file location containing JSON template'), Arg('--template-url', dest='TemplateURL', metavar='URL', help='S3 URL for JSON template')) .required()] LIST_TAGS = ['Capabilities', 'Parameters', 'ResourceTypes'] def print_result(self, result): if result.get('Description'): print self.tabify(('DESCRIPTION', result.get('Description'))) for cap in result.get('Capabilities') or []: print self.tabify(('CAPABILITY', cap)) if result.get('CapabilitiesReason'): print self.tabify(('CAPABILITYREASON', result.get('CapabilitiesReason'))) for res in result.get('ResourceTypes') or []: print self.tabify(('RESOURCETYPES', res)) for param in result.get('Parameters') or []: print self.tabify(('PARAMETER', param.get('ParameterKey'), param.get('NoEcho'), param.get('DefaultValue'), param.get('Description'))) if result.get('Metadata'): print self.tabify(('METADATA', result.get('Metadata')))
class PutUserPolicy(IAMRequest): DESCRIPTION = 'Attach a policy to a user' ARGS = [ Arg('-u', '--user-name', dest='UserName', metavar='USER', required=True, help='user to attach the policy to (required)'), Arg('-p', '--policy-name', dest='PolicyName', metavar='POLICY', required=True, help='name of the policy (required)'), MutuallyExclusiveArgList( Arg('-o', '--policy-content', dest='PolicyDocument', metavar='POLICY_CONTENT', help='the policy to attach'), Arg('-f', '--policy-document', dest='PolicyDocument', metavar='FILE', type=open, help='file containing the policy to attach')).required(), AS_ACCOUNT ]
class PutMetricData(CloudWatchRequest): DESCRIPTION = 'Add data points or statistics to a metric' ARGS = [Arg('-m', '--metric-name', dest='MetricData.member.1.MetricName', metavar='METRIC', required=True, help='name of the metric to add data points to (required)'), Arg('-n', '--namespace', dest='Namespace', required=True, help="the metric's namespace (required)"), MutuallyExclusiveArgList( Arg('-v', '--value', dest='MetricData.member.1.Value', metavar='FLOAT', type=float, help='data value for the metric'), Arg('-s', '--statistic-values', '--statisticValues', dest='MetricData.member.1.StatisticValues', metavar=('Maximum=FLOAT,Minimum=FLOAT,SampleCount=FLOAT,' 'Sum=FLOAT'), type=_statistic_set, help='''statistic values for the metric. Maximum, Minimum, SampleCount, and Sum values are all required.''')) .required(), Arg('-d', '--dimensions', dest='Dimensions.member', metavar='KEY1=VALUE1,KEY2=VALUE2,...', type=delimited_list(',', item_type=cloudwatch_dimension), help='the dimensions of the metric to add data points to'), Arg('-t', '--timestamp', dest='MetricData.member.1.Timestamp', metavar='YYYY-MM-DDThh:mm:ssZ', help='timestamp of the data point'), Arg('-u', '--unit', dest='MetricData.member.1.Unit', metavar='UNIT', help='unit the metric is being reported in')]
class CreateStack(CloudFormationRequest): DESCRIPTION = 'Create a new stack' ARGS = [Arg('StackName', metavar='STACK', help='name of the new stack (required)'), MutuallyExclusiveArgList( Arg('--template-file', dest='TemplateBody', metavar='FILE', type=open, help="file containing the new stack's JSON template"), Arg('--template-url', dest='TemplateURL', metavar='URL', help="URL pointing to the new stack's JSON template")) .required(), Arg('-d', '--disable-rollback', dest='DisableRollback', action='store_true', help='disable rollback on failure'), Arg('-n', '--notification-arns', dest='NotificationARNs', metavar='ARN[,...]', type=delimited_list(','), action='append', help='''SNS ARNs to publish stack actions to'''), Arg('-p', '--parameter', dest='param_sets', route_to=None, metavar='KEY=VALUE', type=parameter_list, action='append', help='''key and value of the parameters to use with the new stack's template, separated by an "=" character'''), Arg('-t', '--timeout', dest='TimeoutInMinutes', type=int, metavar='MINUTES', help='timeout for stack creation'), Arg('--tag', dest='Tags.member', metavar='KEY[=VALUE]', type=binary_tag_def, action='append', help='''key and optional value of the tag to create, separated by an "=" character. If no value is given the tag's value is set to an empty string.''')] def configure(self): CloudFormationRequest.configure(self) stack_params = sum(self.args.get('param_sets') or [], []) self.params['Parameters.member'] = stack_params def print_result(self, result): print result.get('StackId')
class UpdateStack(CloudFormationRequest): DESCRIPTION = 'Update a stack with a new template' ARGS = [ Arg('StackName', metavar='STACK', help='name of the stack to update (required)'), MutuallyExclusiveArgList( Arg('--template-file', dest='TemplateBody', metavar='FILE', type=open, help='file containing a new JSON template for the stack'), Arg('--template-url', dest='TemplateURL', metavar='URL', help='URL pointing to a new JSON template for the stack')). required(), Arg('-p', '--parameter', dest='param_sets', route_to=None, metavar='KEY=VALUE', type=parameter_list, action='append', help='''key and value of the parameters to use with the stack's template, separated by an "=" character''') ] def configure(self): CloudFormationRequest.configure(self) stack_params = sum(self.args.get('param_sets') or [], []) self.params['Parameters.member'] = stack_params def print_result(self, result): print result.get('StackId')
class TerminateInstanceInAutoScalingGroup(AutoScalingRequest, TabifyingMixin): DESCRIPTION = "Manually terminate an auto-scaling instance" ARGS = [Arg('InstanceId', metavar='INSTANCE', help='ID of the instance to terminate (required)'), MutuallyExclusiveArgList(True, Arg('-d', '--decrement-desired-capacity', action='store_const', dest='ShouldDecrementDesiredCapacity', const='true', help='''also reduce the desired capacity of the auto-scaling group by 1'''), Arg('-D', '--no-decrement-desired-capacity', dest='ShouldDecrementDesiredCapacity', action='store_const', const='false', help='''leave the auto-scaling group's desired capacity as-is. A new instance may be launched to compensate for the one being terminated.''')), Arg('--show-long', action='store_true', route_to=None, help='show extra info about the instance being terminated'), Arg('-f', '--force', action='store_true', route_to=None, help=argparse.SUPPRESS)] # for compatibility def print_result(self, result): activity = result['Activity'] bits = ['INSTANCE', activity.get('ActivityId'), activity.get('EndTime'), activity.get('StatusCode'), activity.get('Cause')] if self.args['show_long']: bits.append(activity.get('StatusMessage')) bits.append(activity.get('Progress')) bits.append(activity.get('Description')) bits.append(activity.get('StartTime')) print self.tabify(bits)
class CreateRoute(EC2Request): DESCRIPTION = 'Add a route to a VPC route table' ARGS = [Arg('RouteTableId', metavar='RTABLE', help='ID of the route table to add the route to (required)'), Arg('-r', '--cidr', dest='DestinationCidrBlock', metavar='CIDR', required=True, help='CIDR address block the route should affect (required)'), MutuallyExclusiveArgList( Arg('-g', '--gateway-id', metavar='GATEWAY', route_to=None, help='ID of an Internet, NAT, or virtual private ' 'gateway to target'), Arg('-i', '--instance', dest='InstanceId', metavar='INSTANCE', help='ID of a NAT instance to target'), Arg('-n', '--network-interface', dest='NetworkInterfaceId', help='ID of a network interface to target'), Arg('-p', '--vpc-peering-connection', metavar='PEERCON', dest='VpcPeeringConnectionId', help='ID of a VPC peering connection to target')) .required()] def configure(self): EC2Request.configure(self) gateway_id = self.args['gateway_id'] if gateway_id: if gateway_id.startswith('nat-'): self.params['NatGatewayId'] = gateway_id else: self.params['GatewayId'] = gateway_id def print_result(self, _): target = (self.args.get('GatewayId') or self.args.get('InstanceId') or self.args.get('NetworkInterfaceId') or self.args.get('NatGatewayId') or self.args.get('VpcPeeringConnectionId')) print self.tabify(('ROUTE', target, self.args['DestinationCidrBlock']))
class ValidateTemplate(CloudFormationRequest): DESCRIPTION = 'Validate a template' ARGS = [ MutuallyExclusiveArgList( Arg('--template-file', dest='TemplateBody', metavar='FILE', type=open, help='file location containing JSON template'), Arg('--template-url', dest='TemplateURL', metavar='URL', help='S3 URL for JSON template')).required() ] LIST_TAGS = ['Parameters', 'Capabilities'] def print_result(self, result): print self.tabify(('DESCRIPTION', result.get('Description'))) for cap in result.get('Capabilities') or []: print self.tabify(('CAPABILITY', cap)) if result.get('CapabilitiesReason'): print self.tabify( ('CAPABILITIESREASON', result['CapabilitiesReason'])) for param in result.get('Parameters') or []: print self.tabify( ('PARAMETER', param.get('ParameterKey'), param.get('NoEcho'), param.get('DefaultValue'), param.get('Description')))
class DescribeNetworkInterfaceAttribute(EC2Request): DESCRIPTION = 'Show an attribute of a VPC network interface' ARGS = [ Arg('NetworkInterfaceId', metavar='INTERFACE', help='''ID of the network interface to show info for (required)'''), MutuallyExclusiveArgList( Arg('-d', '--description', dest='Attribute', action='store_const', const='description', help="show the interface's description"), Arg('--source-dest-check', dest='Attribute', action='store_const', const='sourceDestCheck', help='''show whether source/destination address checking is enabled'''), Arg('--group-set', dest='Attribute', action='store_const', const='groupSet', help='''show the security groups the network interface belongs to'''), Arg('-a', '--attachment', dest='Attribute', action='store_const', const='attachment', help='''show info about the interface's attachment (if any)''')).required() ] LIST_TAGS = ['groupSet'] def print_result(self, result): print self.tabify( ('NETWORKINTERFACE', result.get('networkInterfaceId'), self.args['Attribute'])) if self.args['Attribute'] == 'description': print self.tabify( ('DESCRIPTION', result['description'].get('value'))) elif self.args['Attribute'] == 'sourceDestCheck': print self.tabify( ('SOURCEDESTCHECK', result['sourceDestCheck'].get('value'))) elif self.args['Attribute'] == 'groupSet': for group in result.get('groupSet') or []: print self.tabify( ('GROUP', group.get('groupId'), group.get('groupName'))) elif self.args['Attribute'] == 'attachment': attachment = result.get('attachment') if attachment: attachment_info = [ attachment.get(attr) for attr in ('attachmentID', 'deviceIndex', 'status', 'attachTime', 'deleteOnTermination') ] print self.tabify(['ATTACHMENT'] + attachment_info)
class DescribeVpcAttribute(EC2Request): DESCRIPTION = 'Show an attribute of a VPC' ARGS = [ Arg('VpcId', metavar='VPC', help='ID of the VPC to show info for (required)'), MutuallyExclusiveArgList( Arg('-d', '--dns-hostnames', dest='Attribute', action='store_const', const='enableDnsHostnames', help='''show whether instances in the VPC are assigned DNS hostnames'''), Arg('-s', '--dns-support', dest='Attribute', action='store_const', const='enableDnsSupport', help='show whether DNS resolution is enabled')).required() ] def print_result(self, result): if self.args['Attribute'] == 'enableDnsHostnames': print self.tabify( ('RETURN', result['enableDnsHostnames'].get('value'))) elif self.args['Attribute'] == 'enableDnsSupport': print self.tabify( ('RETURN', result['enableDnsSupport'].get('value')))
class DescribeSnapshotAttribute(EC2Request): DESCRIPTION = 'Show information about an attribute of a snapshot' ARGS = [Arg('SnapshotId', metavar='SNAPSHOT', help='snapshot to describe'), MutuallyExclusiveArgList( Arg('-c', '--create-volume-permission', dest='Attribute', action='store_const', const='createVolumePermission', help='display who can create volumes from the snapshot'), Arg('-p', '--product-codes', dest='Attribute', action='store_const', const='productCodes', help='list associated product codes')) .required()] LIST_TAGS = ['createVolumePermission', 'productCodes'] def print_result(self, result): snapshot_id = result.get('snapshotId') for perm in result.get('createVolumePermission', []): for (entity_type, entity_name) in perm.items(): print self.tabify(('createVolumePermission', snapshot_id, entity_type, entity_name)) for code in result.get('productCodes', []): if 'type' in code: code_str = '[{0}: {1}]'.format(code['type'], code.get('productCode')) else: code_str = code.get('productCode') print self.tabify(('productCodes', snapshot_id, 'productCode', code_str))
class PutGroupPolicy(EuareRequest): DESCRIPTION = 'Attach a policy to a group' ARGS = [ Arg('-g', '--group-name', dest='GroupName', metavar='GROUP', required=True, help='group to attach the policy to (required)'), Arg('-p', '--policy-name', dest='PolicyName', metavar='POLICY', required=True, help='name of the policy (required)'), MutuallyExclusiveArgList( True, Arg('-o', '--policy-content', dest='PolicyDocument', metavar='POLICY_CONTENT', help='the policy to attach'), Arg('-f', '--policy-document', dest='PolicyDocument', metavar='FILE', type=open, help='file containing the policy to attach')), AS_ACCOUNT ]
class CreateRole(IAMRequest): DESCRIPTION = 'Create a new role' ARGS = [arg_role(help='name of the new role (required)'), Arg('-p', '--path', dest='Path', help='path for the new role (default: "/")'), MutuallyExclusiveArgList( Arg('-f', dest='AssumeRolePolicyDocument', metavar='FILE', type=file_contents, help='file containing the policy for the new role'), Arg('-s', '--service', dest='service_', metavar='SERVICE', route_to=None, help='''service to allow access to the role (e.g. ec2.amazonaws.com)'''), # For compatibility with a typo in < 3.2.1 Arg('--service_', route_to=None, help=argparse.SUPPRESS)) .required(), Arg('-v', '--verbose', action='store_true', route_to=None, help="print the new role's ARN, GUID, and policy"), AS_ACCOUNT] def preprocess(self): if self.args.get('service_'): statement = {'Effect': 'Allow', 'Principal': {'Service': [self.args['service_']]}, 'Action': ['sts:AssumeRole']} policy = {'Version': '2008-10-17', 'Statement': [statement]} self.params['AssumeRolePolicyDocument'] = json.dumps(policy) def print_result(self, result): if self.args.get('verbose'): print result.get('Role', {}).get('Arn') print result.get('Role', {}).get('RoleId') print urllib.unquote(result.get('Role', {}) .get('AssumeRolePolicyDocument'))
class UpdateAssumeRolePolicy(IAMRequest): DESCRIPTION = ("Update a role's trust policy, the policy that allows " "entities to assume a role") ARGS = [arg_role(help='role to update (required)'), MutuallyExclusiveArgList( Arg('-f', dest='PolicyDocument', metavar='FILE', type=file_contents, help='file containing the policy for the new role'), Arg('-s', '--service', route_to=None, help='''service to allow access to the role (e.g. ec2.amazonaws.com)''')) .required(), Arg('-o', dest='verbose', action='store_true', help="also print the role's new policy"), AS_ACCOUNT] def preprocess(self): if self.args.get('service'): statement = {'Effect': 'Allow', 'Principal': {'Service': [self.args['service']]}, 'Action': ['sts:AssumeRole']} policy = {'Version': '2008-10-17', 'Statement': [statement]} self.params['PolicyDocument'] = json.dumps(policy) def print_result(self, _): if self.args.get('verbose'): print self.params['PolicyDocument']
class UploadSigningCertificate(IAMRequest): DESCRIPTION = 'Upload a signing certificate' ARGS = [ Arg('-u', '--user-name', dest='UserName', metavar='USER', help='''user the signing certificate is for (default: current user)'''), MutuallyExclusiveArgList( Arg('-c', '--certificate-body', dest='CertificateBody', metavar='CERT', help='contents of the new certificate'), Arg('-f', '--certificate-file', dest='CertificateBody', metavar='FILE', type=open, help='file containing the new certificate')).required(), AS_ACCOUNT ] def print_result(self, result): print result.get('Certificate', {}).get('CertificateId')
class CreateNetworkInterface(EC2Request): DESCRIPTION = 'Create a new VPC network interface' ARGS = [ Arg('SubnetId', metavar='SUBNET', help='''subnet to create the new network interface in (required)'''), Arg('-d', '--description', dest='Description', metavar='DESC', help='description for the new network interface'), Arg('-g', '--group', dest='SecurityGroupName', metavar='GROUP', action='append', help='''ID of a security group to add the new network interface to. This option may be used more than once. Each time adds the network interface to an additional security group.'''), Arg('--private-ip-address', metavar='ADDRESS', route_to=None, help='''assign a specific primary private IP address to the new network interface'''), MutuallyExclusiveArgList( Arg('--secondary-address', '--secondary-private-ip-address', metavar='ADDRESS', route_to=None, action='append', help='''assign a specific secondary private IP address to the new network interface. Use this option multiple times to add additional addresses.'''), Arg('--secondary-count', '--secondary-private-ip-address-count', dest='SecondaryPrivateIpAddressCount', metavar='COUNT', type=int, help='''automatically assign a specific number of secondary private IP addresses to the new network interface''')) ] LIST_TAGS = ['groupSet', 'privateIpAddressesSet'] def preprocess(self): addrs = [] if self.args.get('private_ip_address'): addrs.append({ 'PrivateIpAddress': self.args['private_ip_address'], 'Primary': True }) for addr in self.args.get('secondary_private_ip_address') or []: addrs.append({'PrivateIpAddress': addr, 'Primary': False}) self.params['PrivateIpAddresses'] = addrs def print_result(self, result): self.print_interface(result.get('networkInterface') or {})
class CreateLoadBalancer(ELBRequest, TabifyingMixin): DESCRIPTION = ('Create a load balancer\n\nAfter the load balancer is ' 'created, instances must be registered with it separately.') ARGS = [ Arg('LoadBalancerName', metavar='ELB', help='name of the new load balancer (required)'), MutuallyExclusiveArgList( Arg('-s', '--subnets', metavar='SUBNET1,SUBNET2,...', dest='Subnets.member', type=delimited_list(','), help='''[VPC only] subnets the load balancer should run in (required)'''), Arg('-z', '--availability-zones', metavar='ZONE1,ZONE2,...', dest='AvailabilityZones.member', type=delimited_list(','), help='''[Non-VPC only] availability zones the load balancer should run in (required)''')).required(), Arg('-l', '--listener', dest='Listeners.member', action='append', metavar=('"lb-port=PORT, protocol={HTTP,HTTPS,SSL,TCP}, ' 'instance-port=PORT, instance-protocol={HTTP,HTTPS,' 'SSL,TCP}, cert-id=ARN"'), required=True, type=listener, help='''port/protocol settings for the load balancer, where lb-port is the external port number, protocol is the external protocol, instance-port is the back end server port number, instance-protocol is the protocol to use for routing traffic to back end instances, and cert-id is the ARN of the server certificate to use for encrypted connections. lb-port, protocol, and instance-port are required. This option may be used multiple times. (at least 1 required)'''), Arg('-i', '--scheme', dest='Scheme', choices=('internal', ), metavar='internal', help='''[VPC only] "internal" to make the new load balancer private to a VPC'''), Arg('-g', '--security-groups', dest='SecurityGroups.member', metavar='GROUP1,GROUP2,...', type=delimited_list(','), help='''[VPC only] IDs of the security groups to assign to the new load balancer''') ] def print_result(self, result): print self.tabify(('DNS_NAME', result.get('DNSName')))
class EuStore(BaseService): NAME = 'eustore' DESCRIPTION = 'Eucalyptus Image Store' REGION_ENVVAR = 'EUCA_REGION' URL_ENVVAR = 'EUSTORE_URL' ARGS = [MutuallyExclusiveArgList( Arg('--region', dest='userregion', metavar='USER@REGION', help='''name of the region and/or user in config files to use to connect to the service'''), Arg('-U', '--url', help='EuStore service URL'))]
class DescribeImageAttribute(EC2Request): DESCRIPTION = 'Show information about an attribute of an image' ARGS = [Arg('ImageId', metavar='IMAGE', help='image to describe'), MutuallyExclusiveArgList( Arg('-l', '--launch-permission', dest='Attribute', action='store_const', const='launchPermission', help='display launch permissions'), Arg('-p', '--product-codes', dest='Attribute', action='store_const', const='productCodes', help='list associated product codes'), Arg('-B', '--block-device-mapping', dest='Attribute', action='store_const', const='blockDeviceMapping', help='describe block device mappings'), Arg('--kernel', dest='Attribute', action='store_const', const='kernel', help='show associated kernel image ID'), Arg('--ramdisk', dest='Attribute', action='store_const', const='ramdisk', help='show associated ramdisk image ID'), Arg('--description', dest='Attribute', action='store_const', const='description', help="show the image's description")) .required()] LIST_TAGS = ['blockDeviceMapping', 'launchPermission', 'productCodes'] def print_result(self, result): image_id = result.get('imageId') for perm in result.get('launchPermission', []): for (entity_type, entity_name) in perm.items(): print self.tabify(('launchPermission', image_id, entity_type, entity_name)) for code in result.get('productCodes', []): if 'type' in code: code_str = '[{0}: {1}]'.format(code['type'], code.get('productCode')) else: code_str = code.get('productCode') print self.tabify(('productCodes', image_id, 'productCode', code_str)) for blockdev in result.get('blockDeviceMapping', []): blockdev_src = (blockdev.get('virtualName') or blockdev.get('ebs', {}).get('snapshotId')) blockdev_str = '{0}: {1}'.format(blockdev.get('deviceName'), blockdev_src) # TODO: figure out how to print mappings that create new volumes print self.tabify(('blockDeviceMapping', image_id, 'blockDeviceMap', blockdev_str)) if result.get('kernel'): print self.tabify(('kernel', image_id, None, result['kernel'].get('value'))) if result.get('ramdisk'): print self.tabify(('ramdisk', image_id, None, result['ramdisk'].get('value'))) if result.get('description'): print self.tabify(('description', image_id, None, result['description'].get('value')))
class PutAccountPolicy(EuareRequest): DESCRIPTION = '[Eucalyptus cloud admin only] Attach a policy to an account' ARGS = [Arg('-a', '--account-name', dest='AccountName', metavar='ACCOUNT', required=True, help='account to attach the policy to (required)'), Arg('-p', '--policy-name', dest='PolicyName', metavar='POLICY', required=True, help='name of the policy (required)'), MutuallyExclusiveArgList(True, Arg('-o', '--policy-content', dest='PolicyDocument', metavar='POLICY_CONTENT', help='the policy to attach'), Arg('-f', '--policy-document', dest='PolicyDocument', metavar='FILE', type=open, help='file containing the policy to attach'))]
class ReleaseRole(BaseCommand): DESCRIPTION = '''\ Release IAM role credentials The %(prog)s utility removes the credentials created by euare-assumerole(1) by outputting shellcode that deletes the environment variables it creates. Use it inside an eval command to make this process seamless: $ eval `euare-releaserole` Note that if the credentials used to initially assume the role were supplied in the form of environment variables those environment variables will need to be reset: $ source eucarc''' SUITE = Euca2ools ARGS = [ MutuallyExclusiveArgList( Arg('-c', dest='csh_output', route_to=None, action='store_true', help='''generate C-shell commands on stdout (default if SHELL looks like a csh-style shell'''), Arg('-s', dest='sh_output', route_to=None, action='store_true', help='''generate Bourne shell commands on stdout (default if SHELL does not look like a csh-style shell''')) ] def print_result(self, _): for var in ('AWS_ACCESS_KEY_ID', 'AWS_ACCESS_KEY', 'EC2_ACCESS_KEY', 'AWS_SECRET_ACCESS_KEY', 'AWS_SECRET_KEY', 'EC2_SECRET_KEY', 'AWS_SESSION_TOKEN', 'AWS_SECURITY_TOKEN', 'AWS_CREDENTIAL_EXPIRATION', 'EC2_USER_ID', 'AWS_CREDENTIAL_FILE'): if (self.args.get('csh_output') or (not self.args.get('sh_output') and os.getenv('SHELL', '').endswith('csh'))): fmt = 'unsetenv {0};' else: fmt = 'unset {0};' print fmt.format(var) print print '# If you can read this, rerun this program with eval:' print '# eval `{0}`'.format(' '.join( pipes.quote(arg) for arg in sys.argv))
class AssignPrivateIpAddresses(EC2Request): DESCRIPTION = ('Assign one or more private IP addresses to a network ' 'interface\n\nNote that an instance\'s type may affect ' 'the number of addresses it can hold at once.') ARGS = [ Arg('-n', '--network-interface', metavar='INTERFACE', dest='NetworkInterfaceId', help='''ID of the network interface to assign addresses to (required)'''), Arg('positional_interface', nargs='?', route_to=None, help=argparse.SUPPRESS), MutuallyExclusiveArgList( Arg('--secondary-address', '--secondary-private-ip-address', metavar='ADDRESS', dest='PrivateIpAddress', action='append', help='''assign a specific secondary private IP address to the network interface. Use this option multiple times to add additional addresses.'''), Arg('--secondary-count', '--secondary-private-ip-address-count', type=int, dest='SecondaryPrivateIpAddressCount', metavar='COUNT', help='''automatically assign a specific number of secondary private IP addresses to the network interface''')). required(), Arg('--allow-reassignment', dest='AllowReassignment', action='store_true', help='''Allow addresses to be assigned even if they are already associated with other interfaces''') ] def configure(self): EC2Request.configure(self) if self.args.get('positional_interface'): if self.params.get('NetworkInterfaceId'): # Shouldn't be supplied both positionally and optionally raise ArgumentError('unrecognized arguments: {0}'.format( self.args['positional_interface'])) self.params['NetworkInterfaceId'] = \ self.args['positional_interface'] if not self.params.get('NetworkInterfaceId'): raise ArgumentError('argument -n/--network-interface is required')
class MigrateInstances(EC2Request): DESCRIPTION = ('Migrate one instance from its current host, or ' 'migrate all instances from a specific host') ARGS = [ MutuallyExclusiveArgList( Arg('-s', '--source', dest='SourceHost', metavar='HOST', help='remove all instances from a specific host'), Arg('-i', '--instance', dest='InstanceId', metavar='INSTANCE', help='remove one instance from its current host')).required(), MutuallyExclusiveArgList( Arg('--include-dest', action='append', route_to=None, metavar='HOST', help='''allow migration to only a specific host (may be used more than once)'''), Arg('--exclude-dest', action='append', route_to=None, metavar='HOST', help='''allow migration to any host except a specific one (may be used more than once)''')) ] def preprocess(self): if self.args.get('include_dest'): self.params['AllowHosts'] = True self.params['DestinationHost'] = self.args['include_dest'] elif self.args.get('exclude_dest'): self.params['AllowHosts'] = False self.params['DestinationHost'] = self.args['exclude_dest']
class Walrus(requestbuilder.service.BaseService): NAME = 's3' DESCRIPTION = 'Object storage service' AUTH_CLASS = requestbuilder.auth.S3RestAuth REGION_ENVVAR = 'EUCA_REGION' URL_ENVVAR = 'S3_URL' ARGS = [MutuallyExclusiveArgList( Arg('--region', dest='userregion', metavar='USER@REGION', help='''name of the region and/or user in config files to use to connect to the service'''), Arg('-U', '--url', metavar='URL', help='storage service endpoint URL'))] def handle_http_error(self, response): raise AWSError(response)
class ModifyPropertyValue(PropertiesRequest): DESCRIPTION = 'Change the value of a property' ARGS = [ Arg('Name', metavar='PROPERTY', help='name of the property to change (required)'), MutuallyExclusiveArgList( Arg('-v', '--value', dest='Value', help='new value for the property'), Arg('-r', '--reset', dest='Reset', action='store_true', help='reset the property to its default value')).required() ]
class UploadSigningCertificate(IAMRequest): DESCRIPTION = 'Upload a signing certificate' ARGS = [arg_user(help='''user the signing certificate is for (default: current user)'''), MutuallyExclusiveArgList( Arg('-c', '--certificate-body', dest='CertificateBody', metavar='CERT_CONTENT', help='PEM-encoded contents of the new certificate'), Arg('-f', '--certificate-file', dest='CertificateBody', metavar='FILE', type=open, help='file containing the new certificate')) .required(), AS_ACCOUNT] # pylint: disable=no-self-use def print_result(self, result): print result.get('Certificate', {}).get('CertificateId')