def _mounts(self): for i in range(30): command = [ 'efs', 'describe-file-systems', '--region', self.region, '--creation-token', self.token ] file_systems = bin_aws(command, key='FileSystems', max=1) if file_systems[0]['LifeCycleState'] == 'available': command = [ 'efs', 'describe-mount-targets', '--region', self.region, '--file-system-id', self.id ] mount_targets = bin_aws(command, key='MountTargets') for this in self.subnets: if not must.find.dict_in_list(key='SubnetId', needle=this, haystack=mount_targets): command = [ 'efs', 'create-mount-target', '--region', self.region, '--file-system-id', self.id, '--subnet-id', this, '--security-groups' ] command.extend(self.groups) bin_aws(command, decode_output=False) print('Made {0}'.format(command)) # TODO: Log(...) return True else: print('Waiting for EFS {0} to be available'.format(self.id)) sleep(1) raise TimeoutError
def _create(self): """ Create a VPC IPv6 Error: "An error occurred (InvalidParameter) when calling the CreateVpc operation: The parameter amazon-provided-ipv6-cidr-block is not recognized" means IPv6 is not yet available in the region given. https://github.com/aws/aws-cli/issues/2343 :return: """ command = [ 'ec2', 'create-vpc', '--region', self.region, '--cidr-block', self.cidr, ] if self.ipv6: command.append('--amazon-provided-ipv6-cidr-block') result = bin_aws(command) print('Created {0}'.format(command)) # TODO: Log(...) self.id = result['Vpc']['VpcId'] command = [ 'ec2', 'create-tags', '--region', self.region, '--resources', self.id, '--tags', 'Key=Name,Value={0}'.format(self.name) ] bin_aws(command, decode_output=False) print('Named {0}'.format(command)) # TODO: Log(...) return True
def _get(self): """ Get information about VPC from AWS and update self :return: Bool """ command = [ 'ec2', 'describe-tags', '--region', self.region, '--filter', 'Name=resource-type,Values=vpc', 'Name=value,Values={0}'.format(self.name) ] result = bin_aws(command, key='Tags', max=1) if not result: return False self.id = result[0]['ResourceId'] command = [ 'ec2', 'describe-vpcs', '--region', self.region, '--vpc-ids', self.id ] result = bin_aws(command, key='Vpcs', max=1) self.cidr = result[0]['CidrBlock'] self.id = result[0]['VpcId'] if 'Ipv6CidrBlockAssociationSet' in result[0]: self.ipv6 = True else: self.ipv6 = False print('Got {0}'.format(command)) # TODO: Log(...) return True
def _create(self): if self.instance: command = [ 'ec2', 'describe-instances', '--region', self.region, '--instance-ids', self.instance ] reservations = bin_aws(command, key='Reservations') # Force correct AZ self.zone = reservations[0]['Instances'][0]['Placement'][ 'AvailabilityZone'] if not self.zone: raise MissingArgument( '{0}: param "zone" required if "instance" not provided'.format( self.name)) command = [ 'ec2', 'create-volume', '--region', self.region, '--size', self.size, '--volume-type', self.kind, '--availability-zone', self.zone ] result = bin_aws(command) self.id = result['VolumeId'] print('Created {0}'.format(command)) # TODO: Log(...) command = [ 'ec2', 'create-tags', '--region', self.region, '--resources', self.id, '--tags', 'Key=Name,Value={0}'.format(self.name) ] bin_aws(command, decode_output=False) print('Named {0}'.format(command)) # TODO: Log(...) return True
def _groups(self, groups): command = [ 'elb', 'apply-security-groups-to-load-balancer', '--region', self.region, '--load-balancer-name', self.name, '--security-groups' ] command.extend(groups) bin_aws(command, decode_output=False) print('Applied {0}'.format(command)) # TODO: Log(...)
def _rm_zone(self, zone): command = [ 'elb', 'disable-availability-zones-for-load-balancer', '--region', self.region, '--load-balancer-name', self.name, '--availability-zones', zone ] bin_aws(command) self.zones.remove(zone) print('Disabled {0}'.format(command)) # TODO: Log(...) return True
def _detach(self, instances): if not instances: return False command = [ 'elb', 'deregister-instances-from-load-balancer', '--region', self.region, '--load-balancer-name', self.name, '--instances' ] command.extend(instances) bin_aws(command, decode_output=False) print('Detached {0}'.format(command)) # TODO: Log(...)
def _rm_listener(self, listener): command = [ 'elb', 'delete-load-balancer-listeners', '--region', self.region, '--load-balancer-name', self.name, '--load-balancer-ports', str(listener['LoadBalancerPort']) ] bin_aws(command) self.listeners.remove(listener) print('Removed {0}'.format(command)) # TODO: Log(...) return True
def _add_listener(self, listener): command = [ 'elb', 'create-load-balancer-listeners', '--region', self.region, '--load-balancer-name', self.name, '--listeners', str(listener).replace("'", '"') ] bin_aws(command) self.listeners.append(listener) print('Added {0}'.format(command)) # TODO: Log(...) return True
def _rm_instance(self, instances): instances = must.be_list(instances) command = [ 'elb', 'deregister-instances-from-load-balancer', '--region', self.region, '--load-balancer-name', self.name, '--instances' ] command.extend(instances) bin_aws(command) for this in instances: if this in self.instances: self.instances.remove(this) print('Deregistered {0}'.format(command)) # TODO: Log(...) return True
def _add_instance(self, instances): instances = must.be_list(instances) command = [ 'elb', 'register-instances-with-load-balancer', '--region', self.region, '--load-balancer-name', self.name, '--instances' ] command.extend(instances) bin_aws(command) for this in instances: if this not in self.instances: self.instances.append(this) print('Registered {0}'.format(command)) # TODO: Log(...) return True
def _attach(self): if not self.instance and not self.device: return False if not self.instance or not self.device: raise MissingArgument( '{0}: device and instance are both required, else omit both'. format(self.name)) self._wait_for_volume() self._wait_for_instance() command = [ 'ec2', 'attach-volume', '--region', self.region, '--volume-id', self.id, '--instance-id', self.instance, '--device', self.device ] bin_aws(command) print('Attached {0}'.format(command)) # TODO: Log(...)
def _create(self): command = [ 'efs', 'create-file-system', '--region', self.region, '--creation-token', self.token, '--performance-mode', self.kind ] result = bin_aws(command) self.id = result['FileSystemId'] print('Created {0}'.format(command)) # TODO: Log(...) command = [ 'efs', 'create-tags', '--region', self.region, '--file-system-id', self.id, '--tags', 'Key=Name,Value={0}'.format(self.name) ] bin_aws(command, decode_output=False) print('Named {0}'.format(command)) # TODO: Log(...) return True
def _create(self): """ Create a Security Group :return: """ # AWS grants all new SGs this default outbound rule "This is pro-human & anti-machine behavior." default_egress = { 'Ipv6Ranges': [], 'PrefixListIds': [], 'IpRanges': [{ 'CidrIp': '0.0.0.0/0' }], 'UserIdGroupPairs': [], 'IpProtocol': '-1' } command = [ 'ec2', 'create-security-group', '--region', self.region, '--group-name', self.name, '--description', self.description, '--vpc-id', self.vpc ] try: self.id = bin_aws(command, key='GroupId') except AWSDuplicate: return False # OK if it already exists. print('Created {0}'.format(command)) # TODO: Log(...) self.IpPermissions = [] self.IpPermissionsEgress = [default_egress] self.changed = True return True
def _create(self, zones, groups, scheme, listeners): command = [ 'elb', 'create-load-balancer', '--region', self.region, '--load-balancer-name', self.name ] if scheme is not None: command.append('--scheme') command.append(scheme) if groups is not None: command.append('--security-groups') command.extend(groups) if zones is not None: command.append('--availability-zones') command.extend(zones) command.append('--listeners') for listen in listeners: command.append(str(listen).replace( "'", '"')) # Convert Dictionaries to Strings for JSON result = bin_aws(command) self.dns = result['DNSName'] self.zones = zones self.groups = groups self.listeners = listeners print('Created {0}'.format(command)) # TODO: Log(...) return True
def _get(self): command = [ 'ec2', 'describe-tags', '--region', self.region, '--filter', 'Name=resource-type,Values=instance', 'Name=value,Values={0}'.format(self.name) ] result = bin_aws(command)['Tags'] if not result: self.deficit = self.count # Result is []. Deficit is 100%. return False command = [ 'ec2', 'describe-instances', '--region', self.region, '--instance-ids' ] for this in result: command.append(this['ResourceId']) # This does not filter the way we expected it to. # It looks like if any of the instance Ids are not all placed in self.zone then NotFound is raised for all. # if self.zone: # command.append('--filter',) # command.append('Name=availability-zone,Values={0}'.format(self.zone)) reservations = bin_aws(command, key='Reservations') all_instances = [ ] # Will become list() of ALL instances (even terminated) as dict()s for this in reservations: # Extract Instances from each Reservation and merge them into a list() all_instances.extend(this['Instances']) for this in all_instances: if this['State']['Code'] in [0, 16]: # "Pending, Running" if self.zone is None or self.zone == this['Placement'][ 'AvailabilityZone']: self.zones.add(this['Placement']['AvailabilityZone']) self.id.add(this['InstanceId']) if 'PrivateIpAddress' in this: self.private_ips.add(this['PrivateIpAddress']) if 'PublicIpAddress' in this: self.public_ips.add(this['PublicIpAddress']) if 'SubnetId' in this: self.subnets.add(this['SubnetId']) running_count = len(self.id) need_running = self.count if running_count != need_running: self.deficit = need_running - running_count return False print('Got {0}'.format(command)) # TODO: Log(...) return True
def _add_rule(self, ip_permissions, egress): """ :param ip_permissions: Dict of IP Permissions :param egress: Bool :return: Bool """ direction = 'authorize-security-group-ingress' if egress: direction = 'authorize-security-group-egress' command = [ 'ec2', direction, '--region', self.region, '--group-id', self.id, '--ip-permissions', str(ip_permissions).replace("'", '"') ] bin_aws(command) print('Authorized: {0}'.format(ip_permissions)) # TODO: Log(...) self.changed = True return True
def _get(self): command = ['ec2', 'describe-key-pairs', '--region', self.region, '--key-names', self.name] result = bin_aws(command) if not result: return False self.fingerprint = result['KeyPairs'][0]['KeyFingerprint'] print('Got {0}'.format(command)) # TODO: Log(...) return True
def _delete(self): """ Delete myself by my own id. As of 20170114 no other methods call me. You must do `foo._delete()` :return: """ command = [ 'ec2', 'delete-security-group', '--region', self.region, # '--dry-run', '--group-id', self.id ] bin_aws(command, decode_output=False) print('Deleted {0}'.format(command)) # TODO: Log(...) return True
def _get(self): command = [ 'efs', 'describe-file-systems', '--region', self.region, '--creation-token', self.token ] file_systems = bin_aws(command, key='FileSystems', max=1) if not file_systems: return False self.id = file_systems[0]['FileSystemId'] print('Got {0}'.format(command)) # TODO: Log(...) return True
def _create(self): if not self.cidr: raise MissingArgument('Subnet {0} not found and cannot create new one without cidr'.format(self.name)) command = ['ec2', 'create-subnet', '--region', self.region, '--vpc-id', self.vpc, '--cidr-block', self.cidr, ] if self.zone: command.append('--availability-zone') command.append(must.be_string(self.zone)) result = bin_aws(command) print('Created {0}'.format(command)) # TODO: Log(...) self.id = result['Subnet']['SubnetId'] command = ['ec2', 'create-tags', '--region', self.region, '--resources', self.id, '--tags', 'Key=Name,Value={0}'.format(self.name) ] bin_aws(command, decode_output=False) print('Named {0}'.format(command)) # TODO: Log(...) return True
def _create(self): if self.deficit < 1: # This should never usually happen but is possible if the User changes the count to a lower # number after the original instance(s) were created. raise TooMany('Cannot create {0} instances of {1}'.format( self.deficit, self.name)) command = [ 'ec2', 'run-instances', '--region', self.region, '--instance-type', self.size, '--count', str(self.deficit), '--key-name', self.key, '--image-id', self.image, '--security-group-ids' ] command.extend(self.groups) if not self.public: command.append('--no-associate-public-ip-address') if self.zone: placement = { "AvailabilityZone": self.zone, "GroupName": "", "Tenancy": "default", } command.append('--placement') command.append(str(placement).replace("'", '"')) if self.script: command.append('--user-data') command.append('file://{0}'.format(self.script)) instances = bin_aws(command, key='Instances') print('Created {0}'.format(command)) # TODO: Log(...) for this in instances: self.id.add(this['InstanceId']) command = [ 'ec2', 'create-tags', '--region', self.region, '--resources', this['InstanceId'], '--tags', 'Key=Name,Value={0}'.format(self.name) ] bin_aws(command, decode_output=False) print('Named {0}'.format(command)) # TODO: Log(...) self.deficit = 0 return True
def _wait_for_volume(self): for i in range(30): sleep(1) command = [ 'ec2', 'describe-volumes', '--region', self.region, '--volume-ids', self.id ] volumes = bin_aws(command, key='Volumes', max=1) if volumes[0]['State'] == 'available': return True else: print('Waiting for volume {0} to be available'.format(self.id)) raise TimeoutError
def _create(self): command = [ 'rds', 'create-db-instance', '--region', self.region, '--db-instance-identifier', self.name, '--db-name', self.name, '--db-instance-class', self.size, '--engine', self.engine, '--master-username', self.username, '--master-user-password', self.password, '--availability-zone', self.zone, '--allocated-storage', must.be_string(self.gb), '--vpc-security-group-ids' ] command.extend(self.groups) result = bin_aws(command) pprint(result) print('Created {0}'.format(command)) # TODO: Log(...) return True
def _get(self): command = [ 'ec2', 'describe-volumes', '--region', self.region, '--filters', 'Name=attachment.device,Values={0}'.format(self.device), 'Name=attachment.instance-id,Values={0}'.format(self.instance), ] result = bin_aws(command, key='Volumes', max=1) if not result: return False self.id = result[0]['VolumeId'] print('Got {0}'.format(command)) # TODO: Log(...) return True
def _get(self): command = ['ec2', 'describe-subnets', '--region', self.region, '--filter', 'Name=vpc-id,Values={0}'.format(self.vpc), ] if self.cidr: command.append('Name=cidrBlock,Values={0}'.format(self.cidr)) # Prefer to search by CIDR else: command.append('Name=tag:Name,Values={0}'.format(self.name)) # Else by name if User doesnt know the CIDR result = bin_aws(command, key='Subnets', max=1) if not result: return False print('Got {0}'.format(command)) # TODO: Log(...) self.id = result[0]['SubnetId'] self.zone = result[0]['AvailabilityZone'] self.cidr = result[0]['CidrBlock'] return True
def _get(self): """ Get information about Security Group from AWS and update self :return: Bool """ command = [ 'ec2', 'describe-security-groups', '--region', self.region, '--group-names', self.name ] result = bin_aws(command, key='SecurityGroups', max=1) # will raise NotFound if empty me = result[0] self.id = me['GroupId'] self.owner = me['OwnerId'] self.IpPermissions = self._break_out(me['IpPermissions']) self.IpPermissionsEgress = self._break_out(me['IpPermissionsEgress']) print('Got {0}'.format(command)) # TODO: Log(...) return True
def _get(self): command = ['rds', 'describe-db-instances', '--region', self.region] result = bin_aws(command)['DBInstances'] found = must.find.dict_in_list(key='DBName', needle=self.name, haystack=result) if not found: return False self.id = found['DbiResourceId'] self.engine = found['Engine'] self.groups = found['DBSecurityGroups'] self.zone = found['AvailabilityZone'] self.gb = found['AllocatedStorage'] self.username = found['MasterUsername'] if 'Endpoint' in found: self.dns = found['Endpoint']['Address'] self.public = found['PubliclyAccessible'] print('Got {0}'.format(command)) # TODO: Log(...) return True
def _create(self): path_to_key = os.path.join(self.directory, '{0}.pem'.format(self.name)) try: private_key = fileasobj.FileAsObj(path_to_key) except FileNotFoundError: private_key = fileasobj.FileAsObj() private_key.filename = path_to_key if private_key.contents: raise AWSDuplicate('Non-empty file {0} already exists.'.format(path_to_key)) private_key.save() # Make sure we can write to the file before starting work. command = ['ec2', 'create-key-pair', '--region', self.region, '--key-name', self.name, '--query', 'KeyMaterial', '--output', 'text'] result = bin_aws(command, decode_output=False) private_key.add(result) private_key.save() print('Created {0}'.format(command)) # TODO: Log(...) return True
def _wait_for_instance(self): for i in range(30): command = [ 'ec2', 'describe-instances', '--region', self.region, '--instance-ids', self.instance ] reservations = bin_aws(command, key='Reservations') instances = reservations[0]['Instances'] state = instances[0]['State'] if state['Code'] == 0: # Pending print('Waiting for instance {0} to be available'.format( self.instance)) sleep(2) elif state['Code'] == 16: # Running return True else: print('Instance {0} in unexpected state {1}'.format( self.instance, state['Name'])) sleep(1) raise TimeoutError