boto_ec2.py (salt-3002.1) | : | boto_ec2.py (salt-3002.2) | ||
---|---|---|---|---|
# -*- coding: utf-8 -*- | ||||
""" | """ | |||
Manage EC2 | Manage EC2 | |||
.. versionadded:: 2015.8.0 | .. versionadded:: 2015.8.0 | |||
This module provides an interface to the Elastic Compute Cloud (EC2) service | This module provides an interface to the Elastic Compute Cloud (EC2) service | |||
from AWS. | from AWS. | |||
The below code creates a key pair: | The below code creates a key pair: | |||
skipping to change at line 54 | skipping to change at line 53 | |||
.. code-block:: yaml | .. code-block:: yaml | |||
delete-key-pair: | delete-key-pair: | |||
boto_ec2.key_absent: | boto_ec2.key_absent: | |||
- name: mykeypair | - name: mykeypair | |||
- region: eu-west-1 | - region: eu-west-1 | |||
- keyid: GKTADJGHEIQSXMKKRBJ08H | - keyid: GKTADJGHEIQSXMKKRBJ08H | |||
- key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs | - key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs | |||
""" | """ | |||
# Import Python Libs | ||||
from __future__ import absolute_import, print_function, unicode_literals | ||||
import logging | import logging | |||
from time import sleep, time | from time import sleep, time | |||
import salt.utils.data | import salt.utils.data | |||
import salt.utils.dictupdate as dictupdate | import salt.utils.dictupdate as dictupdate | |||
from salt.exceptions import CommandExecutionError, SaltInvocationError | from salt.exceptions import CommandExecutionError, SaltInvocationError | |||
# Import salt libs | ||||
from salt.ext import six | ||||
from salt.ext.six.moves import range | from salt.ext.six.moves import range | |||
log = logging.getLogger(__name__) | log = logging.getLogger(__name__) | |||
def __virtual__(): | def __virtual__(): | |||
""" | """ | |||
Only load if boto is available. | Only load if boto is available. | |||
""" | """ | |||
if "boto_ec2.get_key" in __salt__: | if "boto_ec2.get_key" in __salt__: | |||
return "boto_ec2" | return "boto_ec2" | |||
skipping to change at line 96 | skipping to change at line 89 | |||
): | ): | |||
""" | """ | |||
Ensure key pair is present. | Ensure key pair is present. | |||
""" | """ | |||
ret = {"name": name, "result": True, "comment": "", "changes": {}} | ret = {"name": name, "result": True, "comment": "", "changes": {}} | |||
exists = __salt__["boto_ec2.get_key"](name, region, key, keyid, profile) | exists = __salt__["boto_ec2.get_key"](name, region, key, keyid, profile) | |||
log.debug("exists is %s", exists) | log.debug("exists is %s", exists) | |||
if upload_public is not None and "salt://" in upload_public: | if upload_public is not None and "salt://" in upload_public: | |||
try: | try: | |||
upload_public = __salt__["cp.get_file_str"](upload_public) | upload_public = __salt__["cp.get_file_str"](upload_public) | |||
except IOError as e: | except OSError as e: | |||
log.debug(e) | log.debug(e) | |||
ret["comment"] = "File {0} not found.".format(upload_public) | ret["comment"] = "File {} not found.".format(upload_public) | |||
ret["result"] = False | ret["result"] = False | |||
return ret | return ret | |||
if not exists: | if not exists: | |||
if __opts__["test"]: | if __opts__["test"]: | |||
ret["comment"] = "The key {0} is set to be created.".format(name) | ret["comment"] = "The key {} is set to be created.".format(name) | |||
ret["result"] = None | ret["result"] = None | |||
return ret | return ret | |||
if save_private and not upload_public: | if save_private and not upload_public: | |||
created = __salt__["boto_ec2.create_key"]( | created = __salt__["boto_ec2.create_key"]( | |||
name, save_private, region, key, keyid, profile | name, save_private, region, key, keyid, profile | |||
) | ) | |||
if created: | if created: | |||
ret["result"] = True | ret["result"] = True | |||
ret["comment"] = "The key {0} is created.".format(name) | ret["comment"] = "The key {} is created.".format(name) | |||
ret["changes"]["new"] = created | ret["changes"]["new"] = created | |||
else: | else: | |||
ret["result"] = False | ret["result"] = False | |||
ret["comment"] = "Could not create key {0} ".format(name) | ret["comment"] = "Could not create key {} ".format(name) | |||
elif not save_private and upload_public: | elif not save_private and upload_public: | |||
imported = __salt__["boto_ec2.import_key"]( | imported = __salt__["boto_ec2.import_key"]( | |||
name, upload_public, region, key, keyid, profile | name, upload_public, region, key, keyid, profile | |||
) | ) | |||
if imported: | if imported: | |||
ret["result"] = True | ret["result"] = True | |||
ret["comment"] = "The key {0} is created.".format(name) | ret["comment"] = "The key {} is created.".format(name) | |||
ret["changes"]["old"] = None | ret["changes"]["old"] = None | |||
ret["changes"]["new"] = imported | ret["changes"]["new"] = imported | |||
else: | else: | |||
ret["result"] = False | ret["result"] = False | |||
ret["comment"] = "Could not create key {0} ".format(name) | ret["comment"] = "Could not create key {} ".format(name) | |||
else: | else: | |||
ret["result"] = False | ret["result"] = False | |||
ret["comment"] = "You can either upload or download a private key " | ret["comment"] = "You can either upload or download a private key " | |||
else: | else: | |||
ret["result"] = True | ret["result"] = True | |||
ret["comment"] = "The key name {0} already exists".format(name) | ret["comment"] = "The key name {} already exists".format(name) | |||
return ret | return ret | |||
def key_absent(name, region=None, key=None, keyid=None, profile=None): | def key_absent(name, region=None, key=None, keyid=None, profile=None): | |||
""" | """ | |||
Deletes a key pair | Deletes a key pair | |||
""" | """ | |||
ret = {"name": name, "result": True, "comment": "", "changes": {}} | ret = {"name": name, "result": True, "comment": "", "changes": {}} | |||
exists = __salt__["boto_ec2.get_key"](name, region, key, keyid, profile) | exists = __salt__["boto_ec2.get_key"](name, region, key, keyid, profile) | |||
if exists: | if exists: | |||
if __opts__["test"]: | if __opts__["test"]: | |||
ret["comment"] = "The key {0} is set to be deleted.".format(name) | ret["comment"] = "The key {} is set to be deleted.".format(name) | |||
ret["result"] = None | ret["result"] = None | |||
return ret | return ret | |||
deleted = __salt__["boto_ec2.delete_key"](name, region, key, keyid, prof ile) | deleted = __salt__["boto_ec2.delete_key"](name, region, key, keyid, prof ile) | |||
log.debug("exists is %s", deleted) | log.debug("exists is %s", deleted) | |||
if deleted: | if deleted: | |||
ret["result"] = True | ret["result"] = True | |||
ret["comment"] = "The key {0} is deleted.".format(name) | ret["comment"] = "The key {} is deleted.".format(name) | |||
ret["changes"]["old"] = name | ret["changes"]["old"] = name | |||
else: | else: | |||
ret["result"] = False | ret["result"] = False | |||
ret["comment"] = "Could not delete key {0} ".format(name) | ret["comment"] = "Could not delete key {} ".format(name) | |||
else: | else: | |||
ret["result"] = True | ret["result"] = True | |||
ret["comment"] = "The key name {0} does not exist".format(name) | ret["comment"] = "The key name {} does not exist".format(name) | |||
return ret | return ret | |||
def eni_present( | def eni_present( | |||
name, | name, | |||
subnet_id=None, | subnet_id=None, | |||
subnet_name=None, | subnet_name=None, | |||
private_ip_address=None, | private_ip_address=None, | |||
description=None, | description=None, | |||
groups=None, | groups=None, | |||
source_dest_check=True, | source_dest_check=True, | |||
skipping to change at line 251 | skipping to change at line 244 | |||
if not isinstance(groups, list): | if not isinstance(groups, list): | |||
raise SaltInvocationError("groups must be a list.") | raise SaltInvocationError("groups must be a list.") | |||
if not isinstance(source_dest_check, bool): | if not isinstance(source_dest_check, bool): | |||
raise SaltInvocationError("source_dest_check must be a bool.") | raise SaltInvocationError("source_dest_check must be a bool.") | |||
ret = {"name": name, "result": True, "comment": "", "changes": {}} | ret = {"name": name, "result": True, "comment": "", "changes": {}} | |||
r = __salt__["boto_ec2.get_network_interface"]( | r = __salt__["boto_ec2.get_network_interface"]( | |||
name=name, region=region, key=key, keyid=keyid, profile=profile | name=name, region=region, key=key, keyid=keyid, profile=profile | |||
) | ) | |||
if "error" in r: | if "error" in r: | |||
ret["result"] = False | ret["result"] = False | |||
ret["comment"] = "Error when attempting to find eni: {0}.".format( | ret["comment"] = "Error when attempting to find eni: {}.".format( | |||
r["error"]["message"] | r["error"]["message"] | |||
) | ) | |||
return ret | return ret | |||
if not r["result"]: | if not r["result"]: | |||
if __opts__["test"]: | if __opts__["test"]: | |||
ret["comment"] = "ENI is set to be created." | ret["comment"] = "ENI is set to be created." | |||
if allocate_eip: | if allocate_eip: | |||
ret["comment"] = " ".join( | ret["comment"] = " ".join( | |||
[ | [ | |||
ret["comment"], | ret["comment"], | |||
skipping to change at line 285 | skipping to change at line 278 | |||
private_ip_address=private_ip_address, | private_ip_address=private_ip_address, | |||
description=description, | description=description, | |||
groups=groups, | groups=groups, | |||
region=region, | region=region, | |||
key=key, | key=key, | |||
keyid=keyid, | keyid=keyid, | |||
profile=profile, | profile=profile, | |||
) | ) | |||
if "error" in result_create: | if "error" in result_create: | |||
ret["result"] = False | ret["result"] = False | |||
ret["comment"] = "Failed to create ENI: {0}".format( | ret["comment"] = "Failed to create ENI: {}".format( | |||
result_create["error"]["message"] | result_create["error"]["message"] | |||
) | ) | |||
return ret | return ret | |||
r["result"] = result_create["result"] | r["result"] = result_create["result"] | |||
ret["comment"] = "Created ENI {0}".format(name) | ret["comment"] = "Created ENI {}".format(name) | |||
ret["changes"]["id"] = r["result"]["id"] | ret["changes"]["id"] = r["result"]["id"] | |||
else: | else: | |||
_ret = _eni_attribute( | _ret = _eni_attribute( | |||
r["result"], "description", description, region, key, keyid, profile | r["result"], "description", description, region, key, keyid, profile | |||
) | ) | |||
ret["changes"] = dictupdate.update(ret["changes"], _ret["changes"]) | ret["changes"] = dictupdate.update(ret["changes"], _ret["changes"]) | |||
ret["comment"] = _ret["comment"] | ret["comment"] = _ret["comment"] | |||
if not _ret["result"]: | if not _ret["result"]: | |||
ret["result"] = _ret["result"] | ret["result"] = _ret["result"] | |||
if ret["result"] is False: | if ret["result"] is False: | |||
skipping to change at line 356 | skipping to change at line 349 | |||
if not _ret: | if not _ret: | |||
_ret = __salt__["boto_ec2.release_eip_address"]( | _ret = __salt__["boto_ec2.release_eip_address"]( | |||
public_ip=None, | public_ip=None, | |||
allocation_id=eip_alloc["allocation_id"], | allocation_id=eip_alloc["allocation_id"], | |||
region=region, | region=region, | |||
key=key, | key=key, | |||
keyid=keyid, | keyid=keyid, | |||
profile=profile, | profile=profile, | |||
) | ) | |||
ret["result"] = False | ret["result"] = False | |||
msg = "Failed to assocaite the allocated EIP address wit h the ENI. The EIP {0}".format( | msg = "Failed to assocaite the allocated EIP address wit h the ENI. The EIP {}".format( | |||
"was successfully released." | "was successfully released." | |||
if _ret | if _ret | |||
else "was NOT RELEASED." | else "was NOT RELEASED." | |||
) | ) | |||
ret["comment"] = " ".join([ret["comment"], msg]) | ret["comment"] = " ".join([ret["comment"], msg]) | |||
return ret | return ret | |||
else: | else: | |||
ret["result"] = False | ret["result"] = False | |||
ret["comment"] = " ".join( | ret["comment"] = " ".join( | |||
[ret["comment"], "Failed to allocate an EIP address"] | [ret["comment"], "Failed to allocate an EIP address"] | |||
skipping to change at line 421 | skipping to change at line 414 | |||
ret["result"] = _ret["result"] | ret["result"] = _ret["result"] | |||
if ret["result"] is False: | if ret["result"] is False: | |||
return ret | return ret | |||
return ret | return ret | |||
def _eni_attribute(metadata, attr, value, region, key, keyid, profile): | def _eni_attribute(metadata, attr, value, region, key, keyid, profile): | |||
ret = {"result": True, "comment": "", "changes": {}} | ret = {"result": True, "comment": "", "changes": {}} | |||
if metadata[attr] == value: | if metadata[attr] == value: | |||
return ret | return ret | |||
if __opts__["test"]: | if __opts__["test"]: | |||
ret["comment"] = "ENI set to have {0} updated.".format(attr) | ret["comment"] = "ENI set to have {} updated.".format(attr) | |||
ret["result"] = None | ret["result"] = None | |||
return ret | return ret | |||
result_update = __salt__["boto_ec2.modify_network_interface_attribute"]( | result_update = __salt__["boto_ec2.modify_network_interface_attribute"]( | |||
network_interface_id=metadata["id"], | network_interface_id=metadata["id"], | |||
attr=attr, | attr=attr, | |||
value=value, | value=value, | |||
region=region, | region=region, | |||
key=key, | key=key, | |||
keyid=keyid, | keyid=keyid, | |||
profile=profile, | profile=profile, | |||
) | ) | |||
if "error" in result_update: | if "error" in result_update: | |||
msg = "Failed to update ENI {0}: {1}." | msg = "Failed to update ENI {0}: {1}." | |||
ret["result"] = False | ret["result"] = False | |||
ret["comment"] = msg.format(attr, result_update["error"]["message"]) | ret["comment"] = msg.format(attr, result_update["error"]["message"]) | |||
else: | else: | |||
ret["comment"] = "Updated ENI {0}.".format(attr) | ret["comment"] = "Updated ENI {}.".format(attr) | |||
ret["changes"][attr] = {"old": metadata[attr], "new": value} | ret["changes"][attr] = {"old": metadata[attr], "new": value} | |||
return ret | return ret | |||
def _eni_groups(metadata, groups, region, key, keyid, profile): | def _eni_groups(metadata, groups, region, key, keyid, profile): | |||
ret = {"result": True, "comment": "", "changes": {}} | ret = {"result": True, "comment": "", "changes": {}} | |||
group_ids = [g["id"] for g in metadata["groups"]] | group_ids = [g["id"] for g in metadata["groups"]] | |||
group_ids.sort() | group_ids.sort() | |||
_groups = __salt__["boto_secgroup.convert_to_group_ids"]( | _groups = __salt__["boto_secgroup.convert_to_group_ids"]( | |||
groups, | groups, | |||
vpc_id=metadata["vpc_id"], | vpc_id=metadata["vpc_id"], | |||
skipping to change at line 515 | skipping to change at line 508 | |||
profile | profile | |||
A dict with region, key and keyid, or a pillar key (string) | A dict with region, key and keyid, or a pillar key (string) | |||
that contains a dict with region, key and keyid. | that contains a dict with region, key and keyid. | |||
""" | """ | |||
ret = {"name": name, "result": True, "comment": "", "changes": {}} | ret = {"name": name, "result": True, "comment": "", "changes": {}} | |||
r = __salt__["boto_ec2.get_network_interface"]( | r = __salt__["boto_ec2.get_network_interface"]( | |||
name=name, region=region, key=key, keyid=keyid, profile=profile | name=name, region=region, key=key, keyid=keyid, profile=profile | |||
) | ) | |||
if "error" in r: | if "error" in r: | |||
ret["result"] = False | ret["result"] = False | |||
ret["comment"] = "Error when attempting to find eni: {0}.".format( | ret["comment"] = "Error when attempting to find eni: {}.".format( | |||
r["error"]["message"] | r["error"]["message"] | |||
) | ) | |||
return ret | return ret | |||
if not r["result"]: | if not r["result"]: | |||
if __opts__["test"]: | if __opts__["test"]: | |||
ret["comment"] = "ENI is set to be deleted." | ret["comment"] = "ENI is set to be deleted." | |||
ret["result"] = None | ret["result"] = None | |||
return ret | return ret | |||
else: | else: | |||
if __opts__["test"]: | if __opts__["test"]: | |||
skipping to change at line 544 | skipping to change at line 537 | |||
result_detach = __salt__["boto_ec2.detach_network_interface"]( | result_detach = __salt__["boto_ec2.detach_network_interface"]( | |||
name=name, | name=name, | |||
force=True, | force=True, | |||
region=region, | region=region, | |||
key=key, | key=key, | |||
keyid=keyid, | keyid=keyid, | |||
profile=profile, | profile=profile, | |||
) | ) | |||
if "error" in result_detach: | if "error" in result_detach: | |||
ret["result"] = False | ret["result"] = False | |||
ret["comment"] = "Failed to detach ENI: {0}".format( | ret["comment"] = "Failed to detach ENI: {}".format( | |||
result_detach["error"]["message"] | result_detach["error"]["message"] | |||
) | ) | |||
return ret | return ret | |||
# TODO: Ensure the detach occurs before continuing | # TODO: Ensure the detach occurs before continuing | |||
result_delete = __salt__["boto_ec2.delete_network_interface"]( | result_delete = __salt__["boto_ec2.delete_network_interface"]( | |||
name=name, region=region, key=key, keyid=keyid, profile=profile | name=name, region=region, key=key, keyid=keyid, profile=profile | |||
) | ) | |||
if "error" in result_delete: | if "error" in result_delete: | |||
ret["result"] = False | ret["result"] = False | |||
ret["comment"] = "Failed to delete ENI: {0}".format( | ret["comment"] = "Failed to delete ENI: {}".format( | |||
result_delete["error"]["message"] | result_delete["error"]["message"] | |||
) | ) | |||
return ret | return ret | |||
ret["comment"] = "Deleted ENI {0}".format(name) | ret["comment"] = "Deleted ENI {}".format(name) | |||
ret["changes"]["id"] = None | ret["changes"]["id"] = None | |||
if release_eip and "allocationId" in r["result"]: | if release_eip and "allocationId" in r["result"]: | |||
_ret = __salt__["boto_ec2.release_eip_address"]( | _ret = __salt__["boto_ec2.release_eip_address"]( | |||
public_ip=None, | public_ip=None, | |||
allocation_id=r["result"]["allocationId"], | allocation_id=r["result"]["allocationId"], | |||
region=region, | region=region, | |||
key=key, | key=key, | |||
keyid=keyid, | keyid=keyid, | |||
profile=profile, | profile=profile, | |||
) | ) | |||
skipping to change at line 883 | skipping to change at line 876 | |||
elif len(instances) > 1: | elif len(instances) > 1: | |||
log.debug( | log.debug( | |||
"Multiple instances matching criteria found - cannot determine a singular instance-id" | "Multiple instances matching criteria found - cannot determine a singular instance-id" | |||
) | ) | |||
instance_id = None # No way to know, we'll just have to bail later. ... | instance_id = None # No way to know, we'll just have to bail later. ... | |||
else: | else: | |||
instance_id = instances[0] | instance_id = instances[0] | |||
if _create: | if _create: | |||
if __opts__["test"]: | if __opts__["test"]: | |||
ret["comment"] = "The instance {0} is set to be created.".format(nam e) | ret["comment"] = "The instance {} is set to be created.".format(name ) | |||
ret["result"] = None | ret["result"] = None | |||
return ret | return ret | |||
if image_name: | if image_name: | |||
args = { | args = { | |||
"ami_name": image_name, | "ami_name": image_name, | |||
"region": region, | "region": region, | |||
"key": key, | "key": key, | |||
"keyid": keyid, | "keyid": keyid, | |||
"profile": profile, | "profile": profile, | |||
} | } | |||
skipping to change at line 938 | skipping to change at line 931 | |||
network_interfaces=network_interfaces, | network_interfaces=network_interfaces, | |||
network_interface_name=network_interface_name, | network_interface_name=network_interface_name, | |||
network_interface_id=network_interface_id, | network_interface_id=network_interface_id, | |||
region=region, | region=region, | |||
key=key, | key=key, | |||
keyid=keyid, | keyid=keyid, | |||
profile=profile, | profile=profile, | |||
) | ) | |||
if not r or "instance_id" not in r: | if not r or "instance_id" not in r: | |||
ret["result"] = False | ret["result"] = False | |||
ret["comment"] = "Failed to create instance {0}.".format( | ret["comment"] = "Failed to create instance {}.".format( | |||
instance_name if instance_name else name | instance_name if instance_name else name | |||
) | ) | |||
return ret | return ret | |||
instance_id = r["instance_id"] | instance_id = r["instance_id"] | |||
ret["changes"] = {"old": {}, "new": {}} | ret["changes"] = {"old": {}, "new": {}} | |||
ret["changes"]["old"]["instance_id"] = None | ret["changes"]["old"]["instance_id"] = None | |||
ret["changes"]["new"]["instance_id"] = instance_id | ret["changes"]["new"]["instance_id"] = instance_id | |||
# To avoid issues we only allocate new EIPs at instance creation. | # To avoid issues we only allocate new EIPs at instance creation. | |||
skipping to change at line 994 | skipping to change at line 987 | |||
break | break | |||
else: | else: | |||
log.info( | log.info( | |||
"Waiting up to %s secs for new EIP %s to become available", | "Waiting up to %s secs for new EIP %s to become available", | |||
tries * secs, | tries * secs, | |||
public_ip or allocation_id, | public_ip or allocation_id, | |||
) | ) | |||
time.sleep(secs) | time.sleep(secs) | |||
if not r: | if not r: | |||
ret["result"] = False | ret["result"] = False | |||
ret["comment"] = "Failed to lookup EIP {0}.".format( | ret["comment"] = "Failed to lookup EIP {}.".format( | |||
public_ip or allocation_id | public_ip or allocation_id | |||
) | ) | |||
return ret | return ret | |||
ip = r[0]["public_ip"] | ip = r[0]["public_ip"] | |||
if r[0].get("instance_id"): | if r[0].get("instance_id"): | |||
if r[0]["instance_id"] != instance_id: | if r[0]["instance_id"] != instance_id: | |||
ret["result"] = False | ret["result"] = False | |||
ret["comment"] = ( | ret["comment"] = ( | |||
"EIP {0} is already associated with instance " | "EIP {} is already associated with instance " | |||
"{1}.".format( | "{}.".format( | |||
public_ip if public_ip else allocation_id, r[0]["instanc e_id"] | public_ip if public_ip else allocation_id, r[0]["instanc e_id"] | |||
) | ) | |||
) | ) | |||
return ret | return ret | |||
else: | else: | |||
if __opts__["test"]: | if __opts__["test"]: | |||
ret["comment"] = "Instance {0} to be updated.".format(name) | ret["comment"] = "Instance {} to be updated.".format(name) | |||
ret["result"] = None | ret["result"] = None | |||
return ret | return ret | |||
r = __salt__["boto_ec2.associate_eip_address"]( | r = __salt__["boto_ec2.associate_eip_address"]( | |||
instance_id=instance_id, | instance_id=instance_id, | |||
public_ip=public_ip, | public_ip=public_ip, | |||
allocation_id=allocation_id, | allocation_id=allocation_id, | |||
region=region, | region=region, | |||
key=key, | key=key, | |||
keyid=keyid, | keyid=keyid, | |||
profile=profile, | profile=profile, | |||
) | ) | |||
if r: | if r: | |||
if "new" not in ret["changes"]: | if "new" not in ret["changes"]: | |||
ret["changes"]["new"] = {} | ret["changes"]["new"] = {} | |||
ret["changes"]["new"]["public_ip"] = ip | ret["changes"]["new"]["public_ip"] = ip | |||
else: | else: | |||
ret["result"] = False | ret["result"] = False | |||
ret["comment"] = "Failed to attach EIP to instance {0}.".format( | ret["comment"] = "Failed to attach EIP to instance {}.".format( | |||
instance_name if instance_name else name | instance_name if instance_name else name | |||
) | ) | |||
return ret | return ret | |||
if attributes: | if attributes: | |||
for k, v in six.iteritems(attributes): | for k, v in attributes.items(): | |||
curr = __salt__["boto_ec2.get_attribute"]( | curr = __salt__["boto_ec2.get_attribute"]( | |||
k, | k, | |||
instance_id=instance_id, | instance_id=instance_id, | |||
region=region, | region=region, | |||
key=key, | key=key, | |||
keyid=keyid, | keyid=keyid, | |||
profile=profile, | profile=profile, | |||
) | ) | |||
curr = {} if not isinstance(curr, dict) else curr | curr = {} if not isinstance(curr, dict) else curr | |||
if curr.get(k) == v: | if curr.get(k) == v: | |||
continue | continue | |||
else: | else: | |||
if __opts__["test"]: | if __opts__["test"]: | |||
changed_attrs[ | changed_attrs[ | |||
k | k | |||
] = "The instance attribute {0} is set to be changed from '{ 1}' to '{2}'.".format( | ] = "The instance attribute {} is set to be changed from '{} ' to '{}'.".format( | |||
k, curr.get(k), v | k, curr.get(k), v | |||
) | ) | |||
continue | continue | |||
try: | try: | |||
r = __salt__["boto_ec2.set_attribute"]( | r = __salt__["boto_ec2.set_attribute"]( | |||
attribute=k, | attribute=k, | |||
attribute_value=v, | attribute_value=v, | |||
instance_id=instance_id, | instance_id=instance_id, | |||
region=region, | region=region, | |||
key=key, | key=key, | |||
keyid=keyid, | keyid=keyid, | |||
profile=profile, | profile=profile, | |||
) | ) | |||
except SaltInvocationError as e: | except SaltInvocationError as e: | |||
ret["result"] = False | ret["result"] = False | |||
ret[ | ret[ | |||
"comment" | "comment" | |||
] = "Failed to set attribute {0} to {1} on instance {2}.".fo rmat( | ] = "Failed to set attribute {} to {} on instance {}.".forma t( | |||
k, v, instance_name | k, v, instance_name | |||
) | ) | |||
return ret | return ret | |||
ret["changes"] = ( | ret["changes"] = ( | |||
ret["changes"] if ret["changes"] else {"old": {}, "new": {}} | ret["changes"] if ret["changes"] else {"old": {}, "new": {}} | |||
) | ) | |||
ret["changes"]["old"][k] = curr.get(k) | ret["changes"]["old"][k] = curr.get(k) | |||
ret["changes"]["new"][k] = v | ret["changes"]["new"][k] = v | |||
if __opts__["test"]: | if __opts__["test"]: | |||
if changed_attrs: | if changed_attrs: | |||
ret["changes"]["new"] = changed_attrs | ret["changes"]["new"] = changed_attrs | |||
ret["result"] = None | ret["result"] = None | |||
else: | else: | |||
ret["comment"] = "Instance {0} is in the correct state".format( | ret["comment"] = "Instance {} is in the correct state".format( | |||
instance_name if instance_name else name | instance_name if instance_name else name | |||
) | ) | |||
ret["result"] = True | ret["result"] = True | |||
if tags and instance_id is not None: | if tags and instance_id is not None: | |||
tags = dict(tags) | tags = dict(tags) | |||
curr_tags = dict( | curr_tags = dict( | |||
__salt__["boto_ec2.get_all_tags"]( | __salt__["boto_ec2.get_all_tags"]( | |||
filters={"resource-id": instance_id}, | filters={"resource-id": instance_id}, | |||
region=region, | region=region, | |||
key=key, | key=key, | |||
keyid=keyid, | keyid=keyid, | |||
profile=profile, | profile=profile, | |||
).get(instance_id, {}) | ).get(instance_id, {}) | |||
) | ) | |||
current = set(curr_tags.keys()) | current = set(curr_tags.keys()) | |||
desired = set(tags.keys()) | desired = set(tags.keys()) | |||
remove = list( | remove = list( | |||
current - desired | current - desired | |||
) # Boto explicitly requires a list here and can't cope with a set... | ) # Boto explicitly requires a list here and can't cope with a set... | |||
add = dict([(t, tags[t]) for t in desired - current]) | add = {t: tags[t] for t in desired - current} | |||
replace = dict([(t, tags[t]) for t in tags if tags.get(t) != curr_tags.g | replace = {t: tags[t] for t in tags if tags.get(t) != curr_tags.get(t)} | |||
et(t)]) | ||||
# Tag keys are unique despite the bizarre semantics uses which make it L OOK like they could be duplicative. | # Tag keys are unique despite the bizarre semantics uses which make it L OOK like they could be duplicative. | |||
add.update(replace) | add.update(replace) | |||
if add or remove: | if add or remove: | |||
if __opts__["test"]: | if __opts__["test"]: | |||
ret["changes"]["old"] = ( | ret["changes"]["old"] = ( | |||
ret["changes"]["old"] if "old" in ret["changes"] else {} | ret["changes"]["old"] if "old" in ret["changes"] else {} | |||
) | ) | |||
ret["changes"]["new"] = ( | ret["changes"]["new"] = ( | |||
ret["changes"]["new"] if "new" in ret["changes"] else {} | ret["changes"]["new"] if "new" in ret["changes"] else {} | |||
) | ) | |||
ret["changes"]["old"]["tags"] = curr_tags | ret["changes"]["old"]["tags"] = curr_tags | |||
ret["changes"]["new"]["tags"] = tags | ret["changes"]["new"]["tags"] = tags | |||
ret["comment"] += " Tags would be updated on instance {0}.".for mat( | ret["comment"] += " Tags would be updated on instance {}.".form at( | |||
instance_name if instance_name else name | instance_name if instance_name else name | |||
) | ) | |||
else: | else: | |||
if remove: | if remove: | |||
if not __salt__["boto_ec2.delete_tags"]( | if not __salt__["boto_ec2.delete_tags"]( | |||
resource_ids=instance_id, | resource_ids=instance_id, | |||
tags=remove, | tags=remove, | |||
region=region, | region=region, | |||
key=key, | key=key, | |||
keyid=keyid, | keyid=keyid, | |||
profile=profile, | profile=profile, | |||
): | ): | |||
msg = "Error while deleting tags on instance {0}".format ( | msg = "Error while deleting tags on instance {}".format( | |||
instance_name if instance_name else name | instance_name if instance_name else name | |||
) | ) | |||
log.error(msg) | log.error(msg) | |||
ret["comment"] += " " + msg | ret["comment"] += " " + msg | |||
ret["result"] = False | ret["result"] = False | |||
return ret | return ret | |||
if add: | if add: | |||
if not __salt__["boto_ec2.create_tags"]( | if not __salt__["boto_ec2.create_tags"]( | |||
resource_ids=instance_id, | resource_ids=instance_id, | |||
tags=add, | tags=add, | |||
region=region, | region=region, | |||
key=key, | key=key, | |||
keyid=keyid, | keyid=keyid, | |||
profile=profile, | profile=profile, | |||
): | ): | |||
msg = "Error while creating tags on instance {0}".format ( | msg = "Error while creating tags on instance {}".format( | |||
instance_name if instance_name else name | instance_name if instance_name else name | |||
) | ) | |||
log.error(msg) | log.error(msg) | |||
ret["comment"] += " " + msg | ret["comment"] += " " + msg | |||
ret["result"] = False | ret["result"] = False | |||
return ret | return ret | |||
ret["changes"]["old"] = ( | ret["changes"]["old"] = ( | |||
ret["changes"]["old"] if "old" in ret["changes"] else {} | ret["changes"]["old"] if "old" in ret["changes"] else {} | |||
) | ) | |||
ret["changes"]["new"] = ( | ret["changes"]["new"] = ( | |||
skipping to change at line 1230 | skipping to change at line 1223 | |||
key=key, | key=key, | |||
keyid=keyid, | keyid=keyid, | |||
profile=profile, | profile=profile, | |||
in_states=running_states, | in_states=running_states, | |||
filters=filters, | filters=filters, | |||
) | ) | |||
except CommandExecutionError as e: | except CommandExecutionError as e: | |||
ret["result"] = None | ret["result"] = None | |||
ret["comment"] = ( | ret["comment"] = ( | |||
"Couldn't determine current status of instance " | "Couldn't determine current status of instance " | |||
"{0}.".format(instance_name or name) | "{}.".format(instance_name or name) | |||
) | ) | |||
return ret | return ret | |||
instances = __salt__["boto_ec2.find_instances"]( | instances = __salt__["boto_ec2.find_instances"]( | |||
instance_id=instance_id, | instance_id=instance_id, | |||
region=region, | region=region, | |||
key=key, | key=key, | |||
keyid=keyid, | keyid=keyid, | |||
profile=profile, | profile=profile, | |||
return_objs=True, | return_objs=True, | |||
filters=filters, | filters=filters, | |||
) | ) | |||
if not instances: | if not instances: | |||
ret["result"] = True | ret["result"] = True | |||
ret["comment"] = "Instance {0} is already gone.".format(instance_id) | ret["comment"] = "Instance {} is already gone.".format(instance_id) | |||
return ret | return ret | |||
instance = instances[0] | instance = instances[0] | |||
### Honor 'disableApiTermination' - if you want to override it, first use se t_attribute() to turn it off | ### Honor 'disableApiTermination' - if you want to override it, first use se t_attribute() to turn it off | |||
no_can_do = __salt__["boto_ec2.get_attribute"]( | no_can_do = __salt__["boto_ec2.get_attribute"]( | |||
"disableApiTermination", | "disableApiTermination", | |||
instance_id=instance_id, | instance_id=instance_id, | |||
region=region, | region=region, | |||
key=key, | key=key, | |||
keyid=keyid, | keyid=keyid, | |||
profile=profile, | profile=profile, | |||
) | ) | |||
if no_can_do.get("disableApiTermination") is True: | if no_can_do.get("disableApiTermination") is True: | |||
ret["result"] = False | ret["result"] = False | |||
ret["comment"] = "Termination of instance {0} via the API is disabled.". format( | ret["comment"] = "Termination of instance {} via the API is disabled.".f ormat( | |||
instance_id | instance_id | |||
) | ) | |||
return ret | return ret | |||
if __opts__["test"]: | if __opts__["test"]: | |||
ret["comment"] = "The instance {0} is set to be deleted.".format(name) | ret["comment"] = "The instance {} is set to be deleted.".format(name) | |||
ret["result"] = None | ret["result"] = None | |||
return ret | return ret | |||
r = __salt__["boto_ec2.terminate"]( | r = __salt__["boto_ec2.terminate"]( | |||
instance_id=instance_id, | instance_id=instance_id, | |||
name=instance_name, | name=instance_name, | |||
region=region, | region=region, | |||
key=key, | key=key, | |||
keyid=keyid, | keyid=keyid, | |||
profile=profile, | profile=profile, | |||
) | ) | |||
if not r: | if not r: | |||
ret["result"] = False | ret["result"] = False | |||
ret["comment"] = "Failed to terminate instance {0}.".format(instance_id) | ret["comment"] = "Failed to terminate instance {}.".format(instance_id) | |||
return ret | return ret | |||
ret["changes"]["old"] = {"instance_id": instance_id} | ret["changes"]["old"] = {"instance_id": instance_id} | |||
ret["changes"]["new"] = None | ret["changes"]["new"] = None | |||
if release_eip: | if release_eip: | |||
ip = getattr(instance, "ip_address", None) | ip = getattr(instance, "ip_address", None) | |||
if ip: | if ip: | |||
base_args = { | base_args = { | |||
"region": region, | "region": region, | |||
skipping to change at line 1308 | skipping to change at line 1301 | |||
if getattr(instance, "vpc_id", None): | if getattr(instance, "vpc_id", None): | |||
r = __salt__["boto_ec2.get_eip_address_info"](addresses=ip, **ba se_args) | r = __salt__["boto_ec2.get_eip_address_info"](addresses=ip, **ba se_args) | |||
if r and "allocation_id" in r[0]: | if r and "allocation_id" in r[0]: | |||
alloc_id = r[0]["allocation_id"] | alloc_id = r[0]["allocation_id"] | |||
assoc_id = r[0].get("association_id") | assoc_id = r[0].get("association_id") | |||
else: | else: | |||
# I /believe/ this situation is impossible but let's hedge o ur bets... | # I /believe/ this situation is impossible but let's hedge o ur bets... | |||
ret["result"] = False | ret["result"] = False | |||
ret[ | ret[ | |||
"comment" | "comment" | |||
] = "Can't determine AllocationId for address {0}.".format(i p) | ] = "Can't determine AllocationId for address {}.".format(ip ) | |||
return ret | return ret | |||
else: | else: | |||
public_ip = instance.ip_address | public_ip = instance.ip_address | |||
if assoc_id: | if assoc_id: | |||
# Race here - sometimes the terminate above will already have dr opped this | # Race here - sometimes the terminate above will already have dr opped this | |||
if not __salt__["boto_ec2.disassociate_eip_address"]( | if not __salt__["boto_ec2.disassociate_eip_address"]( | |||
association_id=assoc_id, **base_args | association_id=assoc_id, **base_args | |||
): | ): | |||
log.warning("Failed to disassociate EIP %s.", ip) | log.warning("Failed to disassociate EIP %s.", ip) | |||
if __salt__["boto_ec2.release_eip_address"]( | if __salt__["boto_ec2.release_eip_address"]( | |||
allocation_id=alloc_id, public_ip=public_ip, **base_args | allocation_id=alloc_id, public_ip=public_ip, **base_args | |||
): | ): | |||
log.info("Released EIP address %s", public_ip or r[0]["public_ip "]) | log.info("Released EIP address %s", public_ip or r[0]["public_ip "]) | |||
ret["changes"]["old"]["public_ip"] = public_ip or r[0]["public_i p"] | ret["changes"]["old"]["public_ip"] = public_ip or r[0]["public_i p"] | |||
else: | else: | |||
ret["result"] = False | ret["result"] = False | |||
ret["comment"] = "Failed to release EIP {0}.".format(ip) | ret["comment"] = "Failed to release EIP {}.".format(ip) | |||
return ret | return ret | |||
return ret | return ret | |||
def volume_absent( | def volume_absent( | |||
name, | name, | |||
volume_name=None, | volume_name=None, | |||
volume_id=None, | volume_id=None, | |||
instance_name=None, | instance_name=None, | |||
instance_id=None, | instance_id=None, | |||
skipping to change at line 1417 | skipping to change at line 1410 | |||
instance_id = __salt__["boto_ec2.get_id"]( | instance_id = __salt__["boto_ec2.get_id"]( | |||
name=instance_name, | name=instance_name, | |||
region=region, | region=region, | |||
key=key, | key=key, | |||
keyid=keyid, | keyid=keyid, | |||
profile=profile, | profile=profile, | |||
in_states=running_states, | in_states=running_states, | |||
) | ) | |||
if not instance_id: | if not instance_id: | |||
ret["comment"] = ( | ret["comment"] = ( | |||
"Instance with Name {0} not found. Assuming " | "Instance with Name {} not found. Assuming " | |||
"associated volumes gone.".format(instance_name) | "associated volumes gone.".format(instance_name) | |||
) | ) | |||
return ret | return ret | |||
if instance_id: | if instance_id: | |||
filters.update({"attachment.instance-id": instance_id}) | filters.update({"attachment.instance-id": instance_id}) | |||
if device: | if device: | |||
filters.update({"attachment.device": device}) | filters.update({"attachment.device": device}) | |||
args = {"region": region, "key": key, "keyid": keyid, "profile": profile} | args = {"region": region, "key": key, "keyid": keyid, "profile": profile} | |||
vols = __salt__["boto_ec2.get_all_volumes"](filters=filters, **args) | vols = __salt__["boto_ec2.get_all_volumes"](filters=filters, **args) | |||
if len(vols) < 1: | if len(vols) < 1: | |||
ret["comment"] = "Volume matching criteria not found, assuming already a bsent" | ret["comment"] = "Volume matching criteria not found, assuming already a bsent" | |||
return ret | return ret | |||
if len(vols) > 1: | if len(vols) > 1: | |||
msg = "More than one volume matched criteria, can't continue in state {0 }".format( | msg = "More than one volume matched criteria, can't continue in state {} ".format( | |||
name | name | |||
) | ) | |||
log.error(msg) | log.error(msg) | |||
ret["comment"] = msg | ret["comment"] = msg | |||
ret["result"] = False | ret["result"] = False | |||
return ret | return ret | |||
vol = vols[0] | vol = vols[0] | |||
log.info("Matched Volume ID %s", vol) | log.info("Matched Volume ID %s", vol) | |||
if __opts__["test"]: | if __opts__["test"]: | |||
ret["comment"] = "The volume {0} is set to be deleted.".format(vol) | ret["comment"] = "The volume {} is set to be deleted.".format(vol) | |||
ret["result"] = None | ret["result"] = None | |||
return ret | return ret | |||
if __salt__["boto_ec2.delete_volume"](volume_id=vol, force=True, **args): | if __salt__["boto_ec2.delete_volume"](volume_id=vol, force=True, **args): | |||
ret["comment"] = "Volume {0} deleted.".format(vol) | ret["comment"] = "Volume {} deleted.".format(vol) | |||
ret["changes"] = {"old": {"volume_id": vol}, "new": {"volume_id": None}} | ret["changes"] = {"old": {"volume_id": vol}, "new": {"volume_id": None}} | |||
else: | else: | |||
ret["comment"] = "Error deleting volume {0}.".format(vol) | ret["comment"] = "Error deleting volume {}.".format(vol) | |||
ret["result"] = False | ret["result"] = False | |||
return ret | return ret | |||
def volumes_tagged( | def volumes_tagged( | |||
name, tag_maps, authoritative=False, region=None, key=None, keyid=None, prof ile=None | name, tag_maps, authoritative=False, region=None, key=None, keyid=None, prof ile=None | |||
): | ): | |||
""" | """ | |||
Ensure EC2 volume(s) matching the given filters have the defined tags. | Ensure EC2 volume(s) matching the given filters have the defined tags. | |||
.. versionadded:: 2016.11.0 | .. versionadded:: 2016.11.0 | |||
skipping to change at line 1658 | skipping to change at line 1651 | |||
) | ) | |||
if device is None: | if device is None: | |||
raise SaltInvocationError("Parameter 'device' is required.") | raise SaltInvocationError("Parameter 'device' is required.") | |||
args = {"region": region, "key": key, "keyid": keyid, "profile": profile} | args = {"region": region, "key": key, "keyid": keyid, "profile": profile} | |||
if instance_name: | if instance_name: | |||
instance_id = __salt__["boto_ec2.get_id"]( | instance_id = __salt__["boto_ec2.get_id"]( | |||
name=instance_name, in_states=running_states, **args | name=instance_name, in_states=running_states, **args | |||
) | ) | |||
if not instance_id: | if not instance_id: | |||
raise SaltInvocationError( | raise SaltInvocationError( | |||
"Instance with Name {0} not found.".format(instance_name) | "Instance with Name {} not found.".format(instance_name) | |||
) | ) | |||
instances = __salt__["boto_ec2.find_instances"]( | instances = __salt__["boto_ec2.find_instances"]( | |||
instance_id=instance_id, return_objs=True, **args | instance_id=instance_id, return_objs=True, **args | |||
) | ) | |||
instance = instances[0] | instance = instances[0] | |||
if volume_name: | if volume_name: | |||
filters = {} | filters = {} | |||
filters.update({"tag:Name": volume_name}) | filters.update({"tag:Name": volume_name}) | |||
vols = __salt__["boto_ec2.get_all_volumes"](filters=filters, **args) | vols = __salt__["boto_ec2.get_all_volumes"](filters=filters, **args) | |||
if len(vols) > 1: | if len(vols) > 1: | |||
msg = "More than one volume matched volume name {0}, can't continue in state {1}".format( | msg = "More than one volume matched volume name {}, can't continue i n state {}".format( | |||
volume_name, name | volume_name, name | |||
) | ) | |||
raise SaltInvocationError(msg) | raise SaltInvocationError(msg) | |||
if len(vols) < 1: | if len(vols) < 1: | |||
if __opts__["test"]: | if __opts__["test"]: | |||
ret["comment"] = ( | ret["comment"] = ( | |||
"The volume with name {0} is set to be created and attached" | "The volume with name {} is set to be created and attached" | |||
" on {1}({2}).".format(volume_name, instance_id, device) | " on {}({}).".format(volume_name, instance_id, device) | |||
) | ) | |||
ret["result"] = None | ret["result"] = None | |||
return ret | return ret | |||
_rt = __salt__["boto_ec2.create_volume"]( | _rt = __salt__["boto_ec2.create_volume"]( | |||
zone_name=instance.placement, | zone_name=instance.placement, | |||
size=size, | size=size, | |||
snapshot_id=snapshot_id, | snapshot_id=snapshot_id, | |||
volume_type=volume_type, | volume_type=volume_type, | |||
iops=iops, | iops=iops, | |||
encrypted=encrypted, | encrypted=encrypted, | |||
kms_key_id=kms_key_id, | kms_key_id=kms_key_id, | |||
wait_for_creation=True, | wait_for_creation=True, | |||
**args | **args | |||
) | ) | |||
if "result" in _rt: | if "result" in _rt: | |||
volume_id = _rt["result"] | volume_id = _rt["result"] | |||
else: | else: | |||
raise SaltInvocationError( | raise SaltInvocationError( | |||
"Error creating volume with name {0}.".format(volume_name) | "Error creating volume with name {}.".format(volume_name) | |||
) | ) | |||
_rt = __salt__["boto_ec2.set_volumes_tags"]( | _rt = __salt__["boto_ec2.set_volumes_tags"]( | |||
tag_maps=[ | tag_maps=[ | |||
{ | { | |||
"filters": {"volume_ids": [volume_id]}, | "filters": {"volume_ids": [volume_id]}, | |||
"tags": {"Name": volume_name}, | "tags": {"Name": volume_name}, | |||
} | } | |||
], | ], | |||
**args | **args | |||
) | ) | |||
if _rt["success"] is False: | if _rt["success"] is False: | |||
raise SaltInvocationError( | raise SaltInvocationError( | |||
"Error updating requested volume " | "Error updating requested volume " | |||
"{0} with name {1}. {2}".format( | "{} with name {}. {}".format(volume_id, volume_name, _rt["co | |||
volume_id, volume_name, _rt["comment"] | mment"]) | |||
) | ||||
) | ) | |||
old_dict["volume_id"] = None | old_dict["volume_id"] = None | |||
new_dict["volume_id"] = volume_id | new_dict["volume_id"] = volume_id | |||
else: | else: | |||
volume_id = vols[0] | volume_id = vols[0] | |||
vols = __salt__["boto_ec2.get_all_volumes"]( | vols = __salt__["boto_ec2.get_all_volumes"]( | |||
volume_ids=[volume_id], return_objs=True, **args | volume_ids=[volume_id], return_objs=True, **args | |||
) | ) | |||
if len(vols) < 1: | if len(vols) < 1: | |||
raise SaltInvocationError("Volume {0} do not exist".format(volume_id)) | raise SaltInvocationError("Volume {} do not exist".format(volume_id)) | |||
vol = vols[0] | vol = vols[0] | |||
if vol.zone != instance.placement: | if vol.zone != instance.placement: | |||
raise SaltInvocationError( | raise SaltInvocationError( | |||
("Volume {0} in {1} cannot attach to instance" " {2} in {3}.").forma t( | ("Volume {} in {} cannot attach to instance" " {} in {}.").format( | |||
volume_id, vol.zone, instance_id, instance.placement | volume_id, vol.zone, instance_id, instance.placement | |||
) | ) | |||
) | ) | |||
attach_data = vol.attach_data | attach_data = vol.attach_data | |||
if attach_data is not None and attach_data.instance_id is not None: | if attach_data is not None and attach_data.instance_id is not None: | |||
if instance_id == attach_data.instance_id and device == attach_data.devi ce: | if instance_id == attach_data.instance_id and device == attach_data.devi ce: | |||
ret["comment"] = "The volume {0} is attached on {1}({2}).".format( | ret["comment"] = "The volume {} is attached on {}({}).".format( | |||
volume_id, instance_id, device | volume_id, instance_id, device | |||
) | ) | |||
return ret | return ret | |||
else: | else: | |||
if __opts__["test"]: | if __opts__["test"]: | |||
ret["comment"] = ( | ret["comment"] = ( | |||
"The volume {0} is set to be detached" | "The volume {} is set to be detached" | |||
" from {1}({2} and attached on {3}({4})." | " from {}({} and attached on {}({})." | |||
).format( | ).format( | |||
attach_data.instance_id, | attach_data.instance_id, | |||
attach_data.devic, | attach_data.devic, | |||
volume_id, | volume_id, | |||
instance_id, | instance_id, | |||
device, | device, | |||
) | ) | |||
ret["result"] = None | ret["result"] = None | |||
return ret | return ret | |||
if __salt__["boto_ec2.detach_volume"]( | if __salt__["boto_ec2.detach_volume"]( | |||
volume_id=volume_id, wait_for_detachement=True, **args | volume_id=volume_id, wait_for_detachement=True, **args | |||
): | ): | |||
ret["comment"] = "Volume {0} is detached from {1}({2}).".format( | ret["comment"] = "Volume {} is detached from {}({}).".format( | |||
volume_id, attach_data.instance_id, attach_data.device | volume_id, attach_data.instance_id, attach_data.device | |||
) | ) | |||
old_dict["instance_id"] = attach_data.instance_id | old_dict["instance_id"] = attach_data.instance_id | |||
old_dict["device"] = attach_data.device | old_dict["device"] = attach_data.device | |||
else: | else: | |||
raise SaltInvocationError( | raise SaltInvocationError( | |||
( | ( | |||
"The volume {0} is already attached on instance {1}({2}) ." | "The volume {} is already attached on instance {}({})." | |||
" Failed to detach" | " Failed to detach" | |||
).format(volume_id, attach_data.instance_id, attach_data.dev ice) | ).format(volume_id, attach_data.instance_id, attach_data.dev ice) | |||
) | ) | |||
else: | else: | |||
old_dict["instance_id"] = instance_id | old_dict["instance_id"] = instance_id | |||
old_dict["device"] = None | old_dict["device"] = None | |||
if __opts__["test"]: | if __opts__["test"]: | |||
ret["comment"] = "The volume {0} is set to be attached on {1}({2}).".for mat( | ret["comment"] = "The volume {} is set to be attached on {}({}).".format ( | |||
volume_id, instance_id, device | volume_id, instance_id, device | |||
) | ) | |||
ret["result"] = None | ret["result"] = None | |||
return ret | return ret | |||
if __salt__["boto_ec2.attach_volume"]( | if __salt__["boto_ec2.attach_volume"]( | |||
volume_id=volume_id, instance_id=instance_id, device=device, **args | volume_id=volume_id, instance_id=instance_id, device=device, **args | |||
): | ): | |||
ret["comment"] = " ".join( | ret["comment"] = " ".join( | |||
[ | [ | |||
ret["comment"], | ret["comment"], | |||
"Volume {0} is attached on {1}({2}).".format( | "Volume {} is attached on {}({}).".format( | |||
volume_id, instance_id, device | volume_id, instance_id, device | |||
), | ), | |||
] | ] | |||
) | ) | |||
new_dict["instance_id"] = instance_id | new_dict["instance_id"] = instance_id | |||
new_dict["device"] = device | new_dict["device"] = device | |||
ret["changes"] = {"old": old_dict, "new": new_dict} | ret["changes"] = {"old": old_dict, "new": new_dict} | |||
else: | else: | |||
ret["comment"] = "Error attaching volume {0} to instance {1}({2}).".form at( | ret["comment"] = "Error attaching volume {} to instance {}({}).".format( | |||
volume_id, instance_id, device | volume_id, instance_id, device | |||
) | ) | |||
ret["result"] = False | ret["result"] = False | |||
return ret | return ret | |||
def private_ips_present( | def private_ips_present( | |||
name, | name, | |||
network_interface_name=None, | network_interface_name=None, | |||
network_interface_id=None, | network_interface_id=None, | |||
private_ip_addresses=None, | private_ip_addresses=None, | |||
skipping to change at line 1901 | skipping to change at line 1892 | |||
ips_not_added = [] | ips_not_added = [] | |||
for private_ip in private_ip_addresses: | for private_ip in private_ip_addresses: | |||
if private_ip not in ret["changes"]["new"]: | if private_ip not in ret["changes"]["new"]: | |||
ips_not_added.append(private_ip) | ips_not_added.append(private_ip) | |||
# Display results | # Display results | |||
if ips_not_added: | if ips_not_added: | |||
ret["result"] = False | ret["result"] = False | |||
ret["comment"] = ( | ret["comment"] = ( | |||
"ips on eni: {0}\n" | "ips on eni: {}\n" | |||
"attempted to add: {1}\n" | "attempted to add: {}\n" | |||
"could not add the following ips: {2}\n".format( | "could not add the following ips: {}\n".format( | |||
"\n\t- " + "\n\t- ".join(ret["changes"]["new"]), | "\n\t- " + "\n\t- ".join(ret["changes"]["new"]), | |||
"\n\t- " + "\n\t- ".join(ips_to_add), | "\n\t- " + "\n\t- ".join(ips_to_add), | |||
"\n\t- " + "\n\t- ".join(ips_not_added), | "\n\t- " + "\n\t- ".join(ips_not_added), | |||
) | ) | |||
) | ) | |||
else: | else: | |||
ret["comment"] = "added ips: {0}".format( | ret["comment"] = "added ips: {}".format( | |||
"\n\t- " + "\n\t- ".join(ips_to_add) | "\n\t- " + "\n\t- ".join(ips_to_add) | |||
) | ) | |||
# Verify there were changes | # Verify there were changes | |||
if ret["changes"]["old"] == ret["changes"]["new"]: | if ret["changes"]["old"] == ret["changes"]["new"]: | |||
ret["changes"] = {} | ret["changes"] = {} | |||
else: | else: | |||
# Testing mode, show that there were ips to add | # Testing mode, show that there were ips to add | |||
ret["comment"] = ( | ret["comment"] = "ips on eni: {}\n" "ips that would be added: {}\n". | |||
"ips on eni: {0}\n" | format( | |||
"ips that would be added: {1}\n".format( | "\n\t- " + "\n\t- ".join(ret["changes"]["old"]), | |||
"\n\t- " + "\n\t- ".join(ret["changes"]["old"]), | "\n\t- " + "\n\t- ".join(ips_to_add), | |||
"\n\t- " + "\n\t- ".join(ips_to_add), | ||||
) | ||||
) | ) | |||
ret["changes"] = {} | ret["changes"] = {} | |||
ret["result"] = None | ret["result"] = None | |||
else: | else: | |||
ret["comment"] = "ips on eni: {0}".format( | ret["comment"] = "ips on eni: {}".format( | |||
"\n\t- " + "\n\t- ".join(ret["changes"]["old"]) | "\n\t- " + "\n\t- ".join(ret["changes"]["old"]) | |||
) | ) | |||
# there were no changes since we did not attempt to remove ips | # there were no changes since we did not attempt to remove ips | |||
ret["changes"] = {} | ret["changes"] = {} | |||
return ret | return ret | |||
def private_ips_absent( | def private_ips_absent( | |||
name, | name, | |||
skipping to change at line 2017 | skipping to change at line 2005 | |||
if eni_pip["primary"]: | if eni_pip["primary"]: | |||
primary_private_ip = eni_pip["private_ip_address"] | primary_private_ip = eni_pip["private_ip_address"] | |||
ips_to_remove = [] | ips_to_remove = [] | |||
for private_ip in private_ip_addresses: | for private_ip in private_ip_addresses: | |||
if private_ip in ret["changes"]["old"]: | if private_ip in ret["changes"]["old"]: | |||
ips_to_remove.append(private_ip) | ips_to_remove.append(private_ip) | |||
if private_ip == primary_private_ip: | if private_ip == primary_private_ip: | |||
ret["result"] = False | ret["result"] = False | |||
ret["comment"] = ( | ret["comment"] = ( | |||
"You cannot unassign the primary private ip address ({0}) on an " | "You cannot unassign the primary private ip address ({}) on an " | |||
"eni\n" | "eni\n" | |||
"ips on eni: {1}\n" | "ips on eni: {}\n" | |||
"attempted to remove: {2}\n".format( | "attempted to remove: {}\n".format( | |||
primary_private_ip, | primary_private_ip, | |||
"\n\t- " + "\n\t- ".join(ret["changes"]["old"]), | "\n\t- " + "\n\t- ".join(ret["changes"]["old"]), | |||
"\n\t- " + "\n\t- ".join(private_ip_addresses), | "\n\t- " + "\n\t- ".join(private_ip_addresses), | |||
) | ) | |||
) | ) | |||
ret["changes"] = {} | ret["changes"] = {} | |||
return ret | return ret | |||
if ips_to_remove: | if ips_to_remove: | |||
if not __opts__["test"]: | if not __opts__["test"]: | |||
skipping to change at line 2056 | skipping to change at line 2044 | |||
for eni_pip in eni["result"]["private_ip_addresses"]: | for eni_pip in eni["result"]["private_ip_addresses"]: | |||
ret["changes"]["new"].append(eni_pip["private_ip_address"]) | ret["changes"]["new"].append(eni_pip["private_ip_address"]) | |||
ips_not_removed = [] | ips_not_removed = [] | |||
for private_ip in private_ip_addresses: | for private_ip in private_ip_addresses: | |||
if private_ip in ret["changes"]["new"]: | if private_ip in ret["changes"]["new"]: | |||
ips_not_removed.append(private_ip) | ips_not_removed.append(private_ip) | |||
if ips_not_removed: | if ips_not_removed: | |||
ret["result"] = False | ret["result"] = False | |||
ret["comment"] = ( | ret["comment"] = ( | |||
"ips on eni: {0}\n" | "ips on eni: {}\n" | |||
"attempted to remove: {1}\n" | "attempted to remove: {}\n" | |||
"could not remove the following ips: {2}\n".format( | "could not remove the following ips: {}\n".format( | |||
"\n\t- " + "\n\t- ".join(ret["changes"]["new"]), | "\n\t- " + "\n\t- ".join(ret["changes"]["new"]), | |||
"\n\t- " + "\n\t- ".join(ips_to_remove), | "\n\t- " + "\n\t- ".join(ips_to_remove), | |||
"\n\t- " + "\n\t- ".join(ips_not_removed), | "\n\t- " + "\n\t- ".join(ips_not_removed), | |||
) | ) | |||
) | ) | |||
else: | else: | |||
ret["comment"] = "removed ips: {0}".format( | ret["comment"] = "removed ips: {}".format( | |||
"\n\t- " + "\n\t- ".join(ips_to_remove) | "\n\t- " + "\n\t- ".join(ips_to_remove) | |||
) | ) | |||
# Verify there were changes | # Verify there were changes | |||
if ret["changes"]["old"] == ret["changes"]["new"]: | if ret["changes"]["old"] == ret["changes"]["new"]: | |||
ret["changes"] = {} | ret["changes"] = {} | |||
else: | else: | |||
# Testing mode, show that there were ips to remove | # Testing mode, show that there were ips to remove | |||
ret["comment"] = ( | ret["comment"] = ( | |||
"ips on eni: {0}\n" | "ips on eni: {}\n" | |||
"ips that would be removed: {1}\n".format( | "ips that would be removed: {}\n".format( | |||
"\n\t- " + "\n\t- ".join(ret["changes"]["old"]), | "\n\t- " + "\n\t- ".join(ret["changes"]["old"]), | |||
"\n\t- " + "\n\t- ".join(ips_to_remove), | "\n\t- " + "\n\t- ".join(ips_to_remove), | |||
) | ) | |||
) | ) | |||
ret["changes"] = {} | ret["changes"] = {} | |||
ret["result"] = None | ret["result"] = None | |||
else: | else: | |||
ret["comment"] = "ips on network interface: {0}".format( | ret["comment"] = "ips on network interface: {}".format( | |||
"\n\t- " + "\n\t- ".join(ret["changes"]["old"]) | "\n\t- " + "\n\t- ".join(ret["changes"]["old"]) | |||
) | ) | |||
# there were no changes since we did not attempt to remove ips | # there were no changes since we did not attempt to remove ips | |||
ret["changes"] = {} | ret["changes"] = {} | |||
return ret | return ret | |||
End of changes. 75 change blocks. | ||||
97 lines changed or deleted | 86 lines changed or added |