def share_to_another_region(ami_id, regn, ami_name, account_ids, timeout_sec=900): if not regn == region(): resp = ec2(region=regn).copy_image(SourceRegion=region(), SourceImageId=ami_id, Name=ami_name) ami_id = resp['ImageId'] status = "initial" start = time.time() while status != 'available': time.sleep(2) if time.time() - start > timeout_sec: raise Exception("Failed waiting for status 'available' for " + ami_id + " (timeout: " + str(timeout_sec) + ")") try: images_resp = ec2(region=regn).describe_images(ImageIds=[ami_id]) status = images_resp['Images'][0]['State'] except ClientError: print("Did not find image " + ami_id) perms = {"Add": []} my_acco = resolve_account() for acco in account_ids: if not acco == my_acco: perms['Add'].append({"UserId": acco}) if len(perms['Add']) > 0: ec2(region=regn).modify_image_attribute(ImageId=ami_id, LaunchPermission=perms)
def promote_image(ami_id, job_name): image_name_prefix = re.sub(r'\W', '_', job_name) build_number = time.strftime("%Y%m%d%H%M%S", time.gmtime()) if 'BUILD_NUMBER' in os.environ: build_number = "%04d" % int(os.environ['BUILD_NUMBER']) images_resp = ec2().describe_images(ImageIds=[ami_id]) ami_name = images_resp['Images'][0]['Name'] with open("ami.properties", 'w') as ami_props: ami_props.write("AMI_ID=" + ami_id + "\nNAME=" + ami_name + "\n") ec2().create_tags(Resources=[ami_id], Tags=[{ 'Key': image_name_prefix, 'Value': image_name_prefix + "_" + build_number }])
def resolve_ami(template_doc, session=None): ami_id = "" ami_name = "" ami_created = "" if 'AMI_ID' in os.environ and os.environ['AMI_ID']: ami_id = os.environ['AMI_ID'] if not ami_id and 'Parameters' in template_doc and \ 'paramAmi' in template_doc['Parameters'] and \ 'IMAGE_JOB' in os.environ: image_job = re.sub(r'\W', '_', os.environ['IMAGE_JOB'].lower()) log("Looking for ami with name prefix " + image_job) sorted_images = get_images(image_job) if sorted_images: image = sorted_images[0] ami_id = image['ImageId'] ami_name = image['Name'] ami_created = image['CreationDate'] elif ami_id and 'Parameters' in template_doc and \ 'paramAmi'in template_doc['Parameters']: log("Looking for ami metadata with id " + ami_id) ami_meta = ec2(session=session).describe_images(ImageIds=[ami_id]) log("Result: " + aws_infra_util.json_save(ami_meta)) image = ami_meta['Images'][0] ami_name = image['Name'] ami_created = image['CreationDate'] return ami_id, ami_name, ami_created
def _map_elastic_ip(context, param, value): eip = None if value == "1": eip_res = ec2().allocate_address(Domain='vpc') if eip_res and "PublicIp" in eip_res: eip = eip_res["PublicIp"] ec2().create_tags(Resources=[eip_res['AllocationId']], Tags=[{ "Key": "Name", "Value": context.__class__.__name__.lower() }]) else: try: index = int(value) - 2 eip = context.elastic_ips[index] except (ValueError, IndexError): print("Invalid elastic ip selection " + value) sys.exit(1) return eip
def set_template(self, template): ContextClassBase.set_template(self, template) az_response = ec2().describe_availability_zones() az_names = sorted([ az_data['ZoneName'] for az_data in az_response['AvailabilityZones'] ]) for az_name in az_names: self.template["Resources"]["Fn::Merge"][0]["resourceAsg"][ "Properties"]["AvailabilityZones"].append(az_name) self.template["Resources"]["Fn::Merge"][0]["resourceAsg"][ "Properties"]["VPCZoneIdentifier"].append("paramSubnet" + az_name[-1:].upper())
def _resolve_onwer_named_ami(owner, name): value = None if (owner, name) in owner_amis: return owner_amis[(owner, name)] else: ami_resp = ec2().describe_images(Owners=[owner], Filters=[{"Name": "name", "Values":[name]}]) ami_ids = [image["ImageId"] for image in sorted(ami_resp['Images'], key=itemgetter('CreationDate'), reverse=True)] if ami_ids: value = ami_ids[0] product_amis[(owner, name)] = value return value
def _resolve_product_ami(product_code): value = None if product_code in product_amis: value = product_amis[product_code] else: ami_resp = ec2().describe_images(Filters=[ {"Name": "product-code", "Values": [product_code]}], Owners=["aws-marketplace"]) ami_ids = [image["ImageId"] for image in sorted(ami_resp['Images'], key=itemgetter('CreationDate'), reverse=True)] if ami_ids: value = ami_ids[0] product_amis[product_code] = value return value
def get_images(image_name_prefix, job_tag_function=_has_job_tag): image_name_prefix = re.sub(r'\W', '_', image_name_prefix) ami_data = ec2().describe_images( Filters=[{ 'Name': 'tag-value', 'Values': [image_name_prefix + "_*"] }]) if len(ami_data['Images']) > 0: return [ image for image in sorted(ami_data['Images'], key=itemgetter('CreationDate'), reverse=True) if job_tag_function(image, image_name_prefix) ] else: return []
def _ask_ssh_key(self): self.ssh_key = "Ssh key ({0}):\n1: create new\n" self.ssh_keys = [] self.ssh_key_default = lambda: "1" if "ssh_key" not in self.ask_fields: self.ask_fields.append("ssh_key") index = 2 keys = ec2().describe_key_pairs() if keys and "KeyPairs" in keys: for key in keys["KeyPairs"]: self.ssh_keys.append(key["KeyName"]) self.ssh_key = self.ssh_key + str(index) \ + ": " + key["KeyName"] + "\n" index = index + 1 self.value_mappers["ssh_key"] = _map_ssh_key self.template_transformers.append(lambda myself: _set_first_parameter( myself.template, "paramSshKeyName", myself.ssh_key))
def _ask_elastic_ip(self): self.elastic_ip = "Elastic ip ({0}):\n1: allocate new\n" self.elastic_ips = [] self.elastic_ip_default = lambda: "1" if "elastic_ip" not in self.ask_fields: self.ask_fields.append("elastic_ip") index = 2 eips = ec2().describe_addresses() if eips and "Addresses" in eips: for address in eips["Addresses"]: if "InstanceId" not in address: self.elastic_ips.append(address['PublicIp']) self.elastic_ip = self.elastic_ip + str(index) \ + ": " + address['PublicIp'] + "\n" index = index + 1 self.value_mappers["elastic_ip"] = _map_elastic_ip self.template_transformers.append(lambda myself: _set_first_parameter( myself.template, "paramEip", myself.elastic_ip))
def _map_ssh_key(context, param, value): key_name = None default_name = "ndt-" + context.__class__.__name__.lower() + "-instance" if value == "1": key_name = type_guess( input("Name for new key pair (" + default_name + "): ")) if not key_name: key_name = default_name key_res = ec2().create_key_pair(KeyName=key_name) if key_res and "KeyMaterial" in key_res: proc = Popen(["store-secret.sh", key_name + ".pem"], stdout=PIPE, stdin=PIPE, stderr=PIPE) proc.communicate(input=key_res["KeyMaterial"]) else: try: index = int(value) - 2 key_name = context.ssh_keys[index] except (ValueError, IndexError): print("Invalid ssh key selection " + value) sys.exit(1) return key_name
def _get_instance_info(instance_id): resp = ec2().describe_instances(InstanceIds=[instance_id]) if ("Reservations" in resp and resp["Reservations"] and "Instances" in resp["Reservations"][0] and resp["Reservations"][0]["Instances"]): return resp["Reservations"][0]["Instances"][0]
def _get_tag_response(self): return ec2().describe_tags(Filters=[{ "Name": "resource-id", "Values": [self.instance_id()] }])
def _get_network_yaml(network, vpc_cidr, subnet_prefixlen, subnet_base, network_yaml, common_yaml): subnet_bits = 32 - int(subnet_prefixlen) subnet_size = 2**subnet_bits last_subnet = subnet_base - subnet_size az_response = ec2().describe_availability_zones() az_names = sorted( [az_data['ZoneName'] for az_data in az_response['AvailabilityZones']]) network_yaml['Parameters']['paramVPCCidr']['Default'] = _nts(vpc_cidr) for az_name in az_names: zone_letter = az_name[-1:] zone_upper_letter = zone_letter.upper() last_subnet += subnet_size private_subnet_addr = last_subnet + (len(az_names) * subnet_size) subnet = ipaddr.IPv4Network( str(last_subnet) + "/" + str(subnet_prefixlen)) private_subnet = ipaddr.IPv4Network( str(private_subnet_addr) + "/" + str(subnet_prefixlen)) if zone_letter == 'a': network_yaml['Parameters']['paramPubACidr']['Default'] = _nts( subnet) network_yaml['Parameters']['paramPrivACidr']['Default'] = _nts( private_subnet) network_yaml['Resources']['resourcePubSubnetA']['Properties'][ 'AvailabilityZone'] = az_name network_yaml['Resources']['resourcePrivSubnetA']['Properties'][ 'AvailabilityZone'] = az_name common_yaml['paramNetwork']['Default'] = _nts(network) else: _append_cidr_param(True, zone_upper_letter, _nts(subnet), network_yaml['Parameters']) _append_cidr_param(False, zone_upper_letter, _nts(private_subnet), network_yaml['Parameters']) _append_network_resources(True, zone_upper_letter, network_yaml['Resources'], az_name) _append_network_resources(False, zone_upper_letter, network_yaml['Resources'], az_name) network_yaml['Outputs']['subnet' + zone_upper_letter] = { "Description": "Public Subnet " + zone_upper_letter, "Value": { "Ref": "resourcePubSubnet" + zone_upper_letter }, "Export": { "Name": { "Fn::Join": [ ":", [{ "Ref": "AWS::StackName" }, "publicSubnet" + zone_upper_letter] ] } } } network_yaml['Outputs']['subnetPriv' + zone_upper_letter] = { "Description": "Private Subnet " + zone_upper_letter, "Value": { "Ref": "resourcePrivSubnet" + zone_upper_letter }, "Export": { "Name": { "Fn::Join": [ ":", [{ "Ref": "AWS::StackName" }, "privateSubnet" + zone_upper_letter] ] } } } pub_net = deepcopy(common_yaml['paramSubnetA']) pub_net['Description'] = pub_net[ 'Description'][:-1] + zone_upper_letter pub_net['Default']['StackRef']['paramName'] = \ pub_net['Default']['StackRef']['paramName'][:-1] + zone_upper_letter common_yaml['paramSubnet' + zone_upper_letter] = pub_net priv_net = deepcopy(common_yaml['paramSubnetPrivA']) priv_net['Description'] = pub_net[ 'Description'][:-1] + zone_upper_letter priv_net['Default']['StackRef']['paramName'] = \ priv_net['Default']['StackRef']['paramName'][:-1] + zone_upper_letter common_yaml['paramSubnetPriv' + zone_upper_letter] = priv_net return network_yaml, common_yaml