def main(self, cmd_args): """associate elastic IP address to an (other) instance Args: cmd_args (namedtuple): See add_documentation method. """ address = find_addresses.main(cmd_args.ip) ec2_client = aws.ec2_client(address['region']) all_instances = find_instances.probe_regions() try: instance = next(instance for instance in all_instances if instance['name'] == cmd_args.name) except StopIteration: halt.err(f"Instance named \"{cmd_args.name}\" not found.") if instance['region'] != address['region']: halt.err("Instance and address are in different regions.") if 'instance_name' in address: if instance['name'] == address['instance_name']: halt.err("Address already associated with specified instance.") if 'association_id' in address and cmd_args.force is False: halt.err(f"Elastic IP address {address['ip']} currently in use.", " Append the -f argument to force disassociation.") with aws.ClientErrorHalt(): if 'association_id' in address: ec2_client.disassociate_address( AssociationId=address['association_id']) ec2_client.associate_address(AllocationId=address['allocation_id'], InstanceId=instance['id']) print("") print("Address associated with instance.")
def _create_instance(self, creation_kwargs, user_data, *, dry_run): """create EC2 instance and initialize with user_data Args: creation_kwargs (dict): See what _parse_creation_kwargs returns. user_data (str): See what _process_user_data returns. dry_run (bool): If True, only test if IAM user is allowed to. """ with aws.ClientErrorHalt(allow=["DryRunOperation"]): return self._ec2_client.run_instances( DryRun=dry_run, KeyName=creation_kwargs['key_name'], MinCount=1, MaxCount=1, ImageId=creation_kwargs['ami_id'], InstanceType=creation_kwargs['instance_type'], BlockDeviceMappings=[{ 'DeviceName': creation_kwargs['device_name'], 'Ebs': { 'VolumeSize': creation_kwargs['volume_size'] } }], TagSpecifications=[{ 'ResourceType': "instance", 'Tags': creation_kwargs['tags'] }], SecurityGroupIds=creation_kwargs['sg_ids'], SubnetId=creation_kwargs['subnet_id'], UserData=user_data)['Instances'][0]
def _create_elastic_ip(self, region, instance_id): """allocate new elastic IP address, and associate with instance""" with aws.ClientErrorHalt(): allocation_id = self._ec2_client.allocate_address( Domain="vpc")['AllocationId'] aws.attach_tags(region, allocation_id) self._associate_elastic_ip(instance_id, allocation_id)
def _associate_elastic_ip(self, instance_id, allocation_id): """attempt to assign elastic IP to instance for 60 seconds""" for _ in range(60): with aws.ClientErrorHalt(allow=["InvalidInstanceID"]): self._ec2_client.associate_address(AllocationId=allocation_id, InstanceId=instance_id, AllowReassociation=False) break sleep(1) else: halt.err("Couldn't assign elastic IP to instance.")
def _access_key_usable_waiter(new_key): """waiter for IAM user access key usability (not perfect)""" iam_client = boto3.client("iam", aws_access_key_id=next(iter(new_key)), aws_secret_access_key=next( iter(new_key.values()))) for _ in range(60): with aws.ClientErrorHalt(allow=["InvalidClientTokenId"]): # New IAM user is assumed to have the iam:GetUser permission. iam_client.get_user() break sleep(1) else: halt.err("Access key not usable even after waiting 1 minute.")
def main(self, cmd_args): """disassociate elastic IP address from its instance Args: cmd_args (namedtuple): See add_documentation method. """ address = find_addresses.main(cmd_args.ip) ec2_client = aws.ec2_client(address['region']) if 'association_id' not in address: halt.err("Elastic IP address not associated with anything.") with aws.ClientErrorHalt(): ec2_client.disassociate_address( AssociationId=address['association_id']) print("") print("Elastic IP address disassociated.")
def _request_random_address(self): """request random IPv4 elastic IP address from AWS""" with aws.ClientErrorHalt(): return self._ec2_client.allocate_address(Domain="vpc")