def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.region = self._state.get('region', None)
     self.handle_create_eni_attachment = Handler(
         ['region', 'networkInterfaceId', 'instanceId', 'deviceIndex'],
         handle=self.realize_create_eni_attachment)
Exemplo n.º 2
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.region = self._state.get('region', None)
     self.handle_associate_route_table = Handler(
         ['region', 'routeTableId', 'subnetId'],
         handle=self.realize_associate_route_table)
Exemplo n.º 3
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.region = self._state.get('region', None)
     self.handle_create_vpn_route = Handler(
         ['region', 'vpnConnectionId', 'destinationCidrBlock'],
         handle=self.realize_create_vpn_route)
Exemplo n.º 4
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.handle_create_igw = Handler(['region', 'vpcId'],
                                      handle=self.realize_create_gtw)
     self.handle_tag_update = Handler(['tags'],
                                      after=[self.handle_create_igw],
                                      handle=self.realize_update_tag)
Exemplo n.º 5
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.region = self._state.get('region', None)
     keys = ['region', 'routeTableId', 'destinationCidrBlock', 'destinationIpv6CidrBlock',
             'egressOnlyInternetGatewayId', 'gatewayId', 'instanceId', 'natGatewayId',
             'networkInterfaceId']
     self.handle_create_route = Handler(keys, handle=self.realize_create_route)
Exemplo n.º 6
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.handle_create_vpn_gtw = Handler(
         ["region", "zone", "vpcId"], handle=self.realize_create_vpn_gtw)
     self.handle_tag_update = Handler(["tags"],
                                      after=[self.handle_create_vpn_gtw],
                                      handle=self.realize_update_tag)
Exemplo n.º 7
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.region = self._state.get('region', None)
     self.handle_create_gtw = Handler(
         ['region', 'subnetId', 'allocationId'],
         handle=self.realize_create_gtw)
     self.nat_gtw_id = self._state.get('natGatewayId', None)
Exemplo n.º 8
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.network_acl_id = self._state.get('networkAclId', None)
     self.handle_create_network_acl = Handler(['region', 'vpcId'], handle=self.realize_create_network_acl)
     self.handle_entries = Handler(['entries'], after=[self.handle_create_network_acl]
                                   , handle=self.realize_entries_change)
     self.handle_subnet_association = Handler(['subnetIds'], after=[self.handle_create_network_acl]
                                              , handle=self.realize_subnets_change)
     self.handle_tag_update = Handler(['tags'], after=[self.handle_create_network_acl], handle=self.realize_update_tag)
Exemplo n.º 9
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.handle_create_endpoint = Handler(
         ['region', 'serviceName', 'vpcId'],
         handle=self.realize_create_endpoint)
     self.handle_modify_endpoint = Handler(
         ['policy', 'routeTableIds'],
         after=[self.handle_create_endpoint],
         handle=self.realize_modify_endpoint)
Exemplo n.º 10
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.handle_create_customer_gtw = Handler(
         ['region', 'publicIp', 'bgpAsn', 'type'],
         handle=self.realize_create_customer_gtw)
     self.handle_tag_update = Handler(
         ['tags'],
         after=[self.handle_create_customer_gtw],
         handle=self.realize_update_tag)
Exemplo n.º 11
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.handle_create_endpoint = Handler(
         ["region", "serviceName", "vpcId"],
         handle=self.realize_create_endpoint)
     self.handle_modify_endpoint = Handler(
         ["policy", "routeTableIds"],
         after=[self.handle_create_endpoint],
         handle=self.realize_modify_endpoint,
     )
Exemplo n.º 12
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.handle_create_customer_gtw = Handler(
         ["region", "publicIp", "bgpAsn", "type"],
         handle=self.realize_create_customer_gtw,
     )
     self.handle_tag_update = Handler(
         ["tags"],
         after=[self.handle_create_customer_gtw],
         handle=self.realize_update_tag,
     )
Exemplo n.º 13
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.handle_create_vpn_conn = Handler(
         [
             'region', 'vpnGatewayId', 'customerGatewayId',
             'staticRoutesOnly'
         ],
         handle=self.realize_create_vpn_conn)
     self.handle_tag_update = Handler(['tags'],
                                      after=[self.handle_create_vpn_conn],
                                      handle=self.realize_update_tag)
Exemplo n.º 14
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     handled_keys = [
         'region', 'vpcId', 'domainNameServers', 'domainName', 'ntpServers',
         'netbiosNameServers', 'netbiosNodeType'
     ]
     self.handle_create_dhcp_options = Handler(
         handled_keys, handle=self.realize_create_dhcp_options)
     self.handle_tag_update = Handler(
         ['tags'],
         after=[self.handle_create_dhcp_options],
         handle=self.realize_update_tag)
Exemplo n.º 15
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.region = self._state.get('region', None)
     self.handle_create_route_table = Handler(
         ['region', 'vpcId'], handle=self.realize_create_route_table)
     self.handle_propagate_vpn_gtws = Handler(
         ['propagatingVgws'],
         handle=self.realize_propagate_vpn_gtws,
         after=[self.handle_create_route_table])
     self.handle_tag_update = Handler(
         ['tags'],
         after=[self.handle_create_route_table],
         handle=self.realize_update_tag)
Exemplo n.º 16
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.handle_create_vpn_conn = Handler(
         [
             "region", "vpnGatewayId", "customerGatewayId",
             "staticRoutesOnly"
         ],
         handle=self.realize_create_vpn_conn,
     )
     self.handle_tag_update = Handler(
         ["tags"],
         after=[self.handle_create_vpn_conn],
         handle=self.realize_update_tag,
     )
Exemplo n.º 17
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.region = self._state.get('region', None)
     self.handle_create_eni = Handler([
         'region', 'subnetId', 'primaryPrivateIpAddress',
         'privateIpAddresses', 'secondaryPrivateIpAddressCount'
     ],
                                      handle=self.realize_create_eni)
     self.handle_modify_eni_attrs = Handler(
         ['description', 'securityGroups', 'sourceDestCheck'],
         handle=self.realize_modify_eni_attrs,
         after=[self.handle_create_eni])
     self.handle_tag_update = Handler(['tags'],
                                      after=[self.handle_create_eni],
                                      handle=self.realize_update_tag)
Exemplo n.º 18
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.region = self._state.get("region", None)
     self.handle_create_route_table = Handler(
         ["region", "vpcId"], handle=self.realize_create_route_table)
     self.handle_propagate_vpn_gtws = Handler(
         ["propagatingVgws"],
         handle=self.realize_propagate_vpn_gtws,
         after=[self.handle_create_route_table],
     )
     self.handle_tag_update = Handler(
         ["tags"],
         after=[self.handle_create_route_table],
         handle=self.realize_update_tag,
     )
Exemplo n.º 19
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.region = self._state.get("region", None)
     keys = [
         "region",
         "routeTableId",
         "destinationCidrBlock",
         "destinationIpv6CidrBlock",
         "egressOnlyInternetGatewayId",
         "gatewayId",
         "instanceId",
         "natGatewayId",
         "networkInterfaceId",
     ]
     self.handle_create_route = Handler(keys, handle=self.realize_create_route)
Exemplo n.º 20
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.handle_create_endpoint = Handler(['region', 'serviceName', 'vpcId'], handle=self.realize_create_endpoint)
     self.handle_modify_endpoint = Handler(['policy', 'routeTableIds'],
             after=[self.handle_create_endpoint],
             handle=self.realize_modify_endpoint)
Exemplo n.º 21
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.region = self._state.get('region', None)
     keys = ['region', 'routeTableId', 'destinationCidrBlock', 'destinationIpv6CidrBlock',
             'egressOnlyInternetGatewayId', 'gatewayId', 'instanceId', 'natGatewayId',
             'networkInterfaceId']
     self.handle_create_route = Handler(keys, handle=self.realize_create_route)
Exemplo n.º 22
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.network_acl_id = self._state.get('networkAclId', None)
     self.handle_create_network_acl = Handler(['region', 'vpcId'], handle=self.realize_create_network_acl)
     self.handle_entries = Handler(['entries'], after=[self.handle_create_network_acl]
                                   , handle=self.realize_entries_change)
     self.handle_subnet_association = Handler(['subnetIds'], after=[self.handle_create_network_acl]
                                              , handle=self.realize_subnets_change)
     self.handle_tag_update = Handler(['tags'], after=[self.handle_create_network_acl], handle=self.realize_update_tag)
Exemplo n.º 23
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     handled_keys = [
         "region",
         "vpcId",
         "domainNameServers",
         "domainName",
         "ntpServers",
         "netbiosNameServers",
         "netbiosNodeType",
     ]
     self.handle_create_dhcp_options = Handler(
         handled_keys, handle=self.realize_create_dhcp_options)
     self.handle_tag_update = Handler(
         ["tags"],
         after=[self.handle_create_dhcp_options],
         handle=self.realize_update_tag,
     )
Exemplo n.º 24
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.region = self._state.get('region', None)
     self.handle_create_route_table = Handler(['region', 'vpcId'], handle=self.realize_create_route_table)
     self.handle_propagate_vpn_gtws = Handler(
         ['propagatingVgws'],
         handle=self.realize_propagate_vpn_gtws,
         after=[self.handle_create_route_table])
     self.handle_tag_update = Handler(['tags'], after=[self.handle_create_route_table], handle=self.realize_update_tag)
Exemplo n.º 25
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.region = self._state.get('region', None)
     self.handle_create_eni = Handler(['region', 'subnetId', 'primaryPrivateIpAddress',
                                       'privateIpAddresses', 'secondaryPrivateIpAddressCount'],
                                       handle=self.realize_create_eni)
     self.handle_modify_eni_attrs = Handler(['description', 'securityGroups', 'sourceDestCheck'],
                                            handle=self.realize_modify_eni_attrs,
                                            after=[self.handle_create_eni])
     self.handle_tag_update = Handler(['tags'], after=[self.handle_create_eni], handle=self.realize_update_tag)
Exemplo n.º 26
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.network_acl_id = self._state.get("networkAclId", None)
     self.handle_create_network_acl = Handler(
         ["region", "vpcId"], handle=self.realize_create_network_acl)
     self.handle_entries = Handler(
         ["entries"],
         after=[self.handle_create_network_acl],
         handle=self.realize_entries_change,
     )
     self.handle_subnet_association = Handler(
         ["subnetIds"],
         after=[self.handle_create_network_acl],
         handle=self.realize_subnets_change,
     )
     self.handle_tag_update = Handler(
         ["tags"],
         after=[self.handle_create_network_acl],
         handle=self.realize_update_tag,
     )
Exemplo n.º 27
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.region = self._state.get("region", None)
     self.handle_create_eni = Handler(
         [
             "region",
             "subnetId",
             "primaryPrivateIpAddress",
             "privateIpAddresses",
             "secondaryPrivateIpAddressCount",
         ],
         handle=self.realize_create_eni,
     )
     self.handle_modify_eni_attrs = Handler(
         ["description", "securityGroups", "sourceDestCheck"],
         handle=self.realize_modify_eni_attrs,
         after=[self.handle_create_eni],
     )
     self.handle_tag_update = Handler(["tags"],
                                      after=[self.handle_create_eni],
                                      handle=self.realize_update_tag)
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.handle_create_igw = Handler(['region', 'vpcId'], handle=self.realize_create_gtw)
Exemplo n.º 29
0
 def __init__(self, depl, name, id):
     nixops.resources.ResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
class VPCNetworkInterfaceAttachmentState(nixops.resources.DiffEngineResourceState, EC2CommonState):
    """State of a VPC network interface attachment"""

    state = nixops.util.attr_property("state", nixops.resources.DiffEngineResourceState.MISSING, int)
    access_key_id = nixops.util.attr_property("accessKeyId", None)
    _reserved_keys = EC2CommonState.COMMON_EC2_RESERVED + ['attachmentId']

    @classmethod
    def get_type(cls):
        return "vpc-network-interface-attachment"

    def __init__(self, depl, name, id):
        nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
        self._state = StateDict(depl, id)
        self.region = self._state.get('region', None)
        self.handle_create_eni_attachment = Handler(['region', 'networkInterfaceId', 'instanceId', 'deviceIndex' ],
                                          handle=self.realize_create_eni_attachment)

    def show_type(self):
        s = super(VPCNetworkInterfaceAttachmentState, self).show_type()
        if self.region: s = "{0} [{1}]".format(s, self.region)
        return s

    @property
    def resource_id(self):
        return self._state.get('attachmentId', None)

    def prefix_definition(self, attr):
        return {('resources', 'vpcNetworkInterfaceAttachments'): attr}

    def get_physical_spec(self):
        return { 'attachmentId': self._state.get('attachmentId', None) }

    def get_definition_prefix(self):
        return "resources.vpcNetworkInterfaceAttachments."

    def create_after(self, resources, defn):
        return {r for r in resources if
                isinstance(r, nixops.resources.vpc_network_interface.VPCNetworkInterfaceState) or
                isinstance(r, nixops.backends.ec2.EC2State)}

    def ensure_state_up(self):
        config = self.get_defn()
        self._state["region"] = config["region"]
        if self._state.get('attachmentId', None):
            if self.state != self.UP:
                self.wait_for_eni_attachment(self._state['networkInterfaceId'])

    def wait_for_eni_attachment(self, eni_id):
        while True:
            response = self.get_client().describe_network_interface_attribute(
                Attribute='attachment',
                NetworkInterfaceId=eni_id)
            if response.get('Attachment', None):
                if response['Attachment']['Status'] == 'attached':
                    break
                elif response['Attachment']['Status'] != "attaching":
                    raise Exception("eni attachment {0} in an unexpected state {1}".format(
                        eni_id, response['Attachment']['Status']))
                self.log_continue(".")
                time.sleep(1)
            else:
                raise Exception("eni {} doesn't have any attachment {}".format(eni_id))

        self.log_end(" done")

        with self.depl._db:
            self.state = self.UP

    def realize_create_eni_attachment(self, allow_recreate):
        config = self.get_defn()
        if self.state == self.UP:
            if not allow_recreate:
                raise Exception("network interface attachment {} definition changed and it needs to be recreated"
                                " use --allow-recreate if you want to create a new one".format(self._state['attachmentId']))
            self.warn("network interface attachment definition changed, recreating ...")
            self._destroy()

        self._state['region'] = config['region']
        vm_id = config['instanceId']
        if vm_id.startswith("res-"):
            res = self.depl.get_typed_resource(vm_id[4:].split(".")[0], "ec2")
            vm_id = res.vm_id

        eni_id = config['networkInterfaceId']
        if eni_id.startswith("res-"):
            res = self.depl.get_typed_resource(eni_id[4:].split(".")[0], "vpc-network-interface")
            eni_id = res._state['networkInterfaceId']

        self.log("attaching network interface {0} to instance {1}".format(eni_id, vm_id))
        eni_attachment = self.get_client().attach_network_interface(
            DeviceIndex=config['deviceIndex'],
            InstanceId=vm_id,
            NetworkInterfaceId=eni_id)

        with self.depl._db:
            self.state = self.STARTING
            self._state['attachmentId'] = eni_attachment['AttachmentId']
            self._state['instanceId'] = vm_id
            self._state['deviceIndex'] = config['deviceIndex']
            self._state['networkInterfaceId'] = eni_id

        self.wait_for_eni_attachment(eni_id)

    def wait_for_eni_detachment(self):
        self.log("waiting for eni attachment {0} to be detached from {1}".format(self._state['attachmentId'], self._state["instanceId"]))
        while True:
            response = self.get_client().describe_network_interface_attribute(
                Attribute='attachment',
                NetworkInterfaceId=self._state['networkInterfaceId'])
            if response.get('Attachment', None):
                if response['Attachment']['Status'] == 'detached':
                    break
                elif response['Attachment']['Status'] != "detaching":
                    raise Exception("eni attachment {0} in an unexpected state {1}".format(
                        eni_id, response['Attachment']['Status']))
                self.log_continue(".")
                time.sleep(1)
            else:
                break

        self.log_end(" done")

    def _destroy(self):
        if self.state == self.UP:
            self.log("detaching vpc network interface attachment {}".format(self._state['attachmentId']))
            try:
                self.get_client().detach_network_interface(AttachmentId=self._state['attachmentId'],
                                                      Force=True)
                with self.depl._db:
                    self.state = self.STOPPING

            except botocore.exceptions.ClientError as e:
                if e.response['Error']['Code'] == "InvalidAttachmentID.NotFound":
                    self.warn("network interface attachment {} was already detached".format(self._state['attachmentId']))
                else:
                    raise e
        if self.state == self.STOPPING:
            self.wait_for_eni_detachment()

        with self.depl._db:
            self.state = self.MISSING
            self._state['region'] = None
            self._state['attachmentId'] = None
            self._state['instanceId'] = None
            self._state['deviceIndex'] = None
            self._state['networkInterfaceId'] = None

    def destroy(self, wipe=False):
        self._destroy()
        return True
Exemplo n.º 31
0
class AWSVPNGatewayState(nixops.resources.DiffEngineResourceState,
                         EC2CommonState):
    """State of a AWS VPN gateway."""

    definition_type = AWSVPNGatewayDefinition

    state = nixops.util.attr_property(
        "state", nixops.resources.DiffEngineResourceState.MISSING, int)
    access_key_id = nixops.util.attr_property("accessKeyId", None)
    _reserved_keys = EC2CommonState.COMMON_EC2_RESERVED + ["vpnGatewayId"]

    def __init__(self, depl, name, id):
        nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
        self._state = StateDict(depl, id)
        self.handle_create_vpn_gtw = Handler(
            ["region", "zone", "vpcId"], handle=self.realize_create_vpn_gtw)
        self.handle_tag_update = Handler(["tags"],
                                         after=[self.handle_create_vpn_gtw],
                                         handle=self.realize_update_tag)

    @classmethod
    def get_type(cls):
        return "aws-vpn-gateway"

    def show_type(self):
        s = super(AWSVPNGatewayState, self).show_type()
        if self._state.get("region", None):
            s = "{0} [{1}]".format(s, self._state["region"])
        return s

    @property
    def resource_id(self):
        return self._state.get("vpnGatewayId", None)

    def prefix_definition(self, attr):
        return {("resources", "awsVPNGateways"): attr}

    def get_defintion_prefix(self):
        return "resources.awsVPNGateways."

    def create_after(self, resources, defn):
        return {
            r
            for r in resources
            if isinstance(r, nixops_aws.resources.vpc.VPCState)
        }

    def realize_create_vpn_gtw(self, allow_recreate):
        config: AWSVPNGatewayDefinition = self.get_defn()

        if self.state == self.UP:
            if not allow_recreate:
                raise Exception(
                    "VPN gateway {} defintion changed"
                    " use --allow-recreate if you want to create a new one".
                    format(self._state["vpnGatewayId"]))
            self.warn("VPN gateway changed, recreating...")
            self._destroy()

        self._state["region"] = config.config.region
        vpc_id = config.config.vpcId
        if vpc_id.startswith("res-"):
            res = self.depl.get_typed_resource(vpc_id[4:].split(".")[0], "vpc",
                                               VPCState)
            vpc_id = res._state["vpcId"]

        self.log("creating VPN gateway in zone {}".format(config.config.zone))
        response = self.get_client().create_vpn_gateway(
            AvailabilityZone=config.config.zone, Type="ipsec.1")

        vpn_gtw_id = response["VpnGateway"]["VpnGatewayId"]
        self.log("attaching vpn gateway {0} to vpc {1}".format(
            vpn_gtw_id, vpc_id))
        self.get_client().attach_vpn_gateway(VpcId=vpc_id,
                                             VpnGatewayId=vpn_gtw_id)
        # TODO wait for the attchement state

        with self.depl._db:
            self.state = self.UP
            self._state["vpnGatewayId"] = vpn_gtw_id
            self._state["vpcId"] = vpc_id
            self._state["zone"] = config.config.zone

    def realize_update_tag(self, allow_recreate):
        config: AWSVPNGatewayDefinition = self.get_defn()
        tags = {k: v for k, v in config.config.tags.items()}
        tags.update(self.get_common_tags())
        self.get_client().create_tags(
            Resources=[self._state["vpnGatewayId"]],
            Tags=[{
                "Key": k,
                "Value": tags[k]
            } for k in tags],
        )

    def _destroy(self):
        if self.state != self.UP:
            return
        self.log("detaching vpn gateway {0} from vpc {1}".format(
            self._state["vpnGatewayId"], self._state["vpcId"]))
        try:
            self.get_client().detach_vpn_gateway(
                VpcId=self._state["vpcId"],
                VpnGatewayId=self._state["vpnGatewayId"])
        except botocore.exceptions.ClientError as e:
            if e.response["Error"][
                    "Code"] == "InvalidVpnGatewayAttachment.NotFound":
                self.warn(
                    "VPN gateway '{0}' attachment with VPC '{1}' is invalid".
                    format(self._state["vpnGatewayId"], self._state["vpcId"]))
            else:
                raise e

        # TODO delete VPN connections associated with this VPN gtw
        self.log("deleting vpn gateway {}".format(self._state["vpnGatewayId"]))
        try:
            self.get_client().delete_vpn_gateway(
                VpnGatewayId=self._state["vpnGatewayId"])
        except botocore.exceptions.ClientError as e:
            if e.response["Error"]["Code"] == "InvalidVpnGatewayID.NotFound":
                self.warn("VPN gateway {} was already deleted".format(
                    self._state["vpnGatewayId"]))
            else:
                raise e

        with self.depl._db:
            self.state = self.MISSING
            self._state["region"] = None
            self._state["vpnGatewayId"] = None
            self._state["vpcId"] = None
            self._state["zone"] = None

    def destroy(self, wipe=False):
        self._destroy()
        return True
Exemplo n.º 32
0
class VPCRouteTableState(nixops.resources.DiffEngineResourceState,
                         EC2CommonState):
    """State of a VPC route table"""

    state = nixops.util.attr_property(
        "state", nixops.resources.DiffEngineResourceState.MISSING, int)
    access_key_id = nixops.util.attr_property("accessKeyId", None)
    _reserved_keys = EC2CommonState.COMMON_EC2_RESERVED + ['routeTableId']

    @classmethod
    def get_type(cls):
        return "vpc-route-table"

    def __init__(self, depl, name, id):
        nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
        self._state = StateDict(depl, id)
        self.region = self._state.get('region', None)
        self.handle_create_route_table = Handler(
            ['region', 'vpcId'], handle=self.realize_create_route_table)
        self.handle_propagate_vpn_gtws = Handler(
            ['propagatingVgws'],
            handle=self.realize_propagate_vpn_gtws,
            after=[self.handle_create_route_table])
        self.handle_tag_update = Handler(
            ['tags'],
            after=[self.handle_create_route_table],
            handle=self.realize_update_tag)

    def show_type(self):
        s = super(VPCRouteTableState, self).show_type()
        if self.region: s = "{0} [{1}]".format(s, self.region)
        return s

    @property
    def resource_id(self):
        return self._state.get('routeTableId', None)

    def prefix_definition(self, attr):
        return {('resources', 'vpcRouteTables'): attr}

    def get_physical_spec(self):
        return {'routeTableId': self._state.get('routeTableId', None)}

    def get_definition_prefix(self):
        return "resources.vpcRouteTables."

    def create_after(self, resources, defn):
        return {
            r
            for r in resources if isinstance(r, nixops.resources.vpc.VPCState)
            or isinstance(r, nixops.resources.vpc_subnet.VPCSubnetState)
        }

    def realize_create_route_table(self, allow_recreate):
        config = self.get_defn()

        if self.state == self.UP:
            if not allow_recreate:
                raise Exception(
                    "route table {} definition changed and it needs to be recreated"
                    " use --allow-recreate if you want to create a new one".
                    format(self._state['routeTableId']))
            self.warn("route table definition changed, recreating ...")
            self._destroy()

        self._state['region'] = config['region']

        vpc_id = config['vpcId']
        if vpc_id.startswith("res-"):
            res = self.depl.get_typed_resource(vpc_id[4:].split(".")[0], "vpc")
            vpc_id = res._state['vpcId']

        self.log("creating route table in vpc {}".format(vpc_id))
        route_table = self.get_client().create_route_table(VpcId=vpc_id)

        with self.depl._db:
            self.state = self.UP
            self._state['vpcId'] = vpc_id
            self._state['routeTableId'] = route_table['RouteTable'][
                'RouteTableId']

    def realize_propagate_vpn_gtws(self, allow_recreate):
        config = self.get_defn()
        old_vgws = self._state.get('propagatingVgws', [])
        new_vgws = []

        for vgw in config['propagatingVgws']:
            if vgw.startswith("res-"):
                res = self.depl.get_typed_resource(vgw[4:].split(".")[0],
                                                   "aws-vpn-gateway")
                new_vgws.append(res._state['vpnGatewayId'])
            else:
                new_vgws.append(vgw)

        to_disable = [r for r in old_vgws if r not in new_vgws]
        to_enable = [r for r in new_vgws if r not in old_vgws]

        for vgw in to_disable:
            self.log(
                "disabling virtual gateway route propagation for {}".format(
                    vgw))
            self.get_client().disable_vgw_route_propagation(
                GatewayId=vgw, RouteTableId=self._state['routeTableId'])
        for vgw in to_enable:
            self.log(
                "enabling virtual gateway route propagation for {}".format(
                    vgw))
            self.get_client().enable_vgw_route_propagation(
                GatewayId=vgw, RouteTableId=self._state['routeTableId'])

        with self.depl._db:
            self._state['propagatingVgws'] = new_vgws

    def realize_update_tag(self, allow_recreate):
        config = self.get_defn()
        tags = config['tags']
        tags.update(self.get_common_tags())
        self.get_client().create_tags(Resources=[self._state['routeTableId']],
                                      Tags=[{
                                          "Key": k,
                                          "Value": tags[k]
                                      } for k in tags])

    def _destroy(self):
        if self.state != self.UP: return
        self.log("deleting route table {}".format(self._state['routeTableId']))
        try:
            self.get_client().delete_route_table(
                RouteTableId=self._state['routeTableId'])
        except botocore.exceptions.ClientError as error:
            if error.response['Error'][
                    'Code'] == "InvalidRouteTableID.NotFound":
                self.warn("route table {} was already deleted".format(
                    self._state['routeTableId']))
            else:
                raise error

        with self.depl._db:
            self.state = self.MISSING
            self._state['vpcId'] = None
            self._state['routeTableId'] = None

    def destroy(self, wipe=False):
        self._destroy()
        return True
Exemplo n.º 33
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.region = self._state.get('region', None)
     self.handle_create_gtw = Handler(['region', 'subnetId', 'allocationId'], handle=self.realize_create_gtw)
     self.nat_gtw_id = self._state.get('natGatewayId', None)
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.region = self._state.get('region', None)
     self.handle_associate_route_table = Handler(['region', 'routeTableId', 'subnetId'], handle=self.realize_associate_route_table)
class VPCEgressOnlyInternetGatewayState(nixops.resources.DiffEngineResourceState, EC2CommonState):
    """State of a VPC egress only internet gateway."""
    state = nixops.util.attr_property("state", nixops.resources.DiffEngineResourceState.MISSING, int)
    access_key_id = nixops.util.attr_property("accessKeyId", None)
    _reserved_keys = EC2CommonState.COMMON_EC2_RESERVED + ["egressOnlyInternetGatewayId"]

    def __init__(self, depl, name, id):
        nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
        self._state = StateDict(depl, id)
        self.handle_create_igw = Handler(['region', 'vpcId'], handle=self.realize_create_gtw)

    @classmethod
    def get_type(cls):
        return "vpc-egress-only-internet-gateway"

    def show_type(self):
        s = super(VPCEgressOnlyInternetGatewayState, self).show_type()
        if self._state.get('region', None): s = "{0} [{1}]".format(s, self._state['region'])
        return s

    @property
    def resource_id(self):
        return self._state.get('egressOnlyInternetGatewayId', None)

    def prefix_definition(self, attr):
        return {('resources', 'vpcEgressOnlyInternetGateways'): attr}

    def get_defintion_prefix(self):
        return "resources.vpcEgressOnlyInternetGateways."

    def create_after(self, resources, defn):
        return {r for r in resources if
                isinstance(r, nixops.resources.vpc.VPCState) or
                isinstance(r, nixops.resources.elastic_ip.ElasticIPState)}

    def realize_create_gtw(self, allow_recreate):
        config = self.get_defn()

        if self.state == self.UP:
            if not allow_recreate:
                raise Exception("egress only internet gateway {} defintion changed"
                                " use --allow-recreate if you want to create a new one".format(
                                    self._state['egressOnlyInternetGatewayId']))
            self.warn("egress only internet gateway changed, recreating...")
            self._destroy()

        self._state['region'] = config['region']

        vpc_id = config['vpcId']
        if vpc_id.startswith("res-"):
            res = self.depl.get_typed_resource(vpc_id[4:].split(".")[0], "vpc")
            vpc_id = res._state['vpcId']

        self.log("creating egress only internet gateway in region {0}, vpc {1}".format(self._state['region'], vpc_id))
        response = self.get_client().create_egress_only_internet_gateway(VpcId=vpc_id)
        igw_id = response['EgressOnlyInternetGateway']['EgressOnlyInternetGatewayId']

        with self.depl._db:
            self.state = self.UP
            self._state['region'] = config['region']
            self._state['vpcId'] = vpc_id
            self._state['egressOnlyInternetGatewayId'] = igw_id

    def _destroy(self):
        if self.state != self.UP: return
        self.log("deleting egress only internet gateway {0}".format(self._state['egressOnlyInternetGatewayId']))
        self.get_client().delete_egress_only_internet_gateway(EgressOnlyInternetGatewayId=self._state['egressOnlyInternetGatewayId'])

        with self.depl._db:
            self.state = self.MISSING
            self._state['region'] = None
            self._state['vpcId'] = None
            self._state['egressOnlyInternetGatewayId'] = None

    def destroy(self, wipe=False):
        self._destroy()
        return True
Exemplo n.º 36
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.handle_create_vpn_gtw = Handler(['region', 'zone', 'vpcId'], handle=self.realize_create_vpn_gtw)
     self.handle_tag_update = Handler(['tags'], after=[self.handle_create_vpn_gtw], handle=self.realize_update_tag)
Exemplo n.º 37
0
class VPCRouteState(nixops.resources.DiffEngineResourceState, EC2CommonState):
    """State of a VPC route"""

    state = nixops.util.attr_property("state", nixops.resources.DiffEngineResourceState.MISSING, int)
    access_key_id = nixops.util.attr_property("accessKeyId", None)
    _reserved_keys = EC2CommonState.COMMON_EC2_RESERVED
    TARGETS = ['egressOnlyInternetGatewayId', 'gatewayId', 'instanceId', 'natGatewayId', 'networkInterfaceId']

    @classmethod
    def get_type(cls):
        return "vpc-route"

    def __init__(self, depl, name, id):
        nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
        self._state = StateDict(depl, id)
        self.region = self._state.get('region', None)
        keys = ['region', 'routeTableId', 'destinationCidrBlock', 'destinationIpv6CidrBlock',
                'egressOnlyInternetGatewayId', 'gatewayId', 'instanceId', 'natGatewayId',
                'networkInterfaceId']
        self.handle_create_route = Handler(keys, handle=self.realize_create_route)

    def show_type(self):
        s = super(VPCRouteState, self).show_type()
        if self.region: s = "{0} [{1}]".format(s, self.region)
        return s

    @property
    def resource_id(self):
        return (self._state.get('destinationCidrBlock', None) or self._state.get('destinationIpv6CidrBlock', None))

    def prefix_definition(self, attr):
        return {('resources', 'vpcRoutes'): attr}

    def get_definition_prefix(self):
        return "resources.vpcRoutes."

    def create_after(self, resources, defn):
        return {r for r in resources if
                isinstance(r, nixops.resources.vpc_route_table.VPCRouteTableState) or
                isinstance(r, nixops.resources.vpc_internet_gateway.VPCInternetGatewayState) or
                isinstance(r, nixops.resources.vpc_nat_gateway.VPCNatGatewayState)}

    def realize_create_route(self, allow_recreate):
        config = self.get_defn()

        if self.state == self.UP:
            if not allow_recreate:
                raise Exception("route {} definition changed and it needs to be recreated"
                                " use --allow-recreate if you want to create a new one".format(self.name))
            self.warn("route definition changed, recreating ...")
            self._destroy()

        self._state['region'] = config['region']

        rtb_id = config['routeTableId']
        if rtb_id.startswith("res-"):
            res = self.depl.get_typed_resource(rtb_id[4:].split(".")[0], "vpc-route-table")
            rtb_id = res._state['routeTableId']

        route = dict()
        config = self.get_defn()
        num_targets = 0
        for item in self.TARGETS:
            if config[item]:
                num_targets+=1
                target = item

        if num_targets > 1:
            raise Exception("you should specify only 1 target from {}".format(str(self.TARGETS)))

        if (config['destinationCidrBlock'] is not None) and (config['destinationIpv6CidrBlock'] is not None):
            raise Exception("you can't set both destinationCidrBlock and destinationIpv6CidrBlock in one route")

        if config['destinationCidrBlock'] is not None: destination = 'destinationCidrBlock'
        if config['destinationIpv6CidrBlock'] is not None: destination = 'destinationIpv6CidrBlock'

        def retrieve_defn(option):
            cfg = config[option]
            if cfg.startswith("res-"):
                name = cfg[4:].split(".")[0]
                res_type = cfg.split(".")[1]
                attr = cfg.split(".")[2] if len(cfg.split(".")) > 2 else option
                res = self.depl.get_typed_resource(name, res_type)
                return res._state[attr]
            else:
                return cfg

        route['RouteTableId'] = rtb_id
        route[self.upper(target)] = retrieve_defn(target)
        route[self.upper(destination)] = config[destination]

        self.log("creating route {0} => {1} in route table {2}".format(retrieve_defn(target), config[destination], rtb_id))
        self.get_client().create_route(**route)

        with self.depl._db:
            self.state = self.UP
            self._state[target] = route[self.upper(target)]
            self._state[destination] = config[destination]
            self._state['routeTableId'] = rtb_id

    def upper(self, option):
        return "%s%s" % (option[0].upper(), option[1:])

    def _destroy(self):
        if self.state != self.UP: return
        destination = 'destinationCidrBlock' if ('destinationCidrBlock' in self._state.keys()) else 'destinationIpv6CidrBlock'
        self.log("deleting route to {0} from route table {1}".format(self._state[destination], self._state['routeTableId']))
        try:
            args = dict()
            args[self.upper(destination)] = self._state[destination]
            args['RouteTableId'] = self._state['routeTableId']
            self.get_client().delete_route(**args)
        except botocore.exceptions.ClientError as error:
            if error.response['Error']['Code'] == "InvalidRoute.NotFound":
                self.warn("route was already deleted")
            else:
                raise error

        with self.depl._db:
            self.state = self.MISSING
            self._state['routeTableId'] = None
            self._state[destination] = None
            for target in self.TARGETS:
                self._state[target] = None

    def destroy(self, wipe=False):
        self._destroy()
        return True
Exemplo n.º 38
0
class AWSVPNGatewayState(nixops.resources.DiffEngineResourceState, EC2CommonState):
    """State of a AWS VPN gateway."""
    state = nixops.util.attr_property("state", nixops.resources.DiffEngineResourceState.MISSING, int)
    access_key_id = nixops.util.attr_property("accessKeyId", None)
    _reserved_keys = EC2CommonState.COMMON_EC2_RESERVED + ["vpnGatewayId"]

    def __init__(self, depl, name, id):
        nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
        self._state = StateDict(depl, id)
        self.handle_create_vpn_gtw = Handler(['region', 'zone', 'vpcId'], handle=self.realize_create_vpn_gtw)
        self.handle_tag_update = Handler(['tags'], after=[self.handle_create_vpn_gtw], handle=self.realize_update_tag)

    @classmethod
    def get_type(cls):
        return "aws-vpn-gateway"

    def show_type(self):
        s = super(AWSVPNGatewayState, self).show_type()
        if self._state.get('region', None): s = "{0} [{1}]".format(s, self._state['region'])
        return s

    @property
    def resource_id(self):
        return self._state.get('vpnGatewayId', None)

    def prefix_definition(self, attr):
        return {('resources', 'awsVPNGateways'): attr}

    def get_defintion_prefix(self):
        return "resources.awsVPNGateways."

    def create_after(self, resources, defn):
        return {r for r in resources if
                isinstance(r, nixops.resources.vpc.VPCState)}

    def realize_create_vpn_gtw(self, allow_recreate):
        config = self.get_defn()

        if self.state == self.UP:
            if not allow_recreate:
                raise Exception("VPN gateway {} defintion changed"
                                " use --allow-recreate if you want to create a new one".format(
                                    self._state['vpnGatewayId']))
            self.warn("VPN gateway changed, recreating...")
            self._destroy()

        self._state['region'] = config['region']
        vpc_id = config['vpcId']
        if vpc_id.startswith("res-"):
            res = self.depl.get_typed_resource(vpc_id[4:].split(".")[0], "vpc")
            vpc_id = res._state['vpcId']

        self.log("creating VPN gateway in zone {}".format(config['zone']))
        response = self.get_client().create_vpn_gateway(
            AvailabilityZone=config['zone'],
            Type="ipsec.1")

        vpn_gtw_id = response['VpnGateway']['VpnGatewayId']
        self.log("attaching vpn gateway {0} to vpc {1}".format(vpn_gtw_id, vpc_id))
        self.get_client().attach_vpn_gateway(
            VpcId=vpc_id,
            VpnGatewayId=vpn_gtw_id)
        #TODO wait for the attchement state

        with self.depl._db:
            self.state = self.UP
            self._state['vpnGatewayId'] = vpn_gtw_id
            self._state['vpcId'] = vpc_id
            self._state['zone'] = config['zone']

    def realize_update_tag(self, allow_recreate):
        config = self.get_defn()
        tags = config['tags']
        tags.update(self.get_common_tags())
        self.get_client().create_tags(Resources=[self._state['vpnGatewayId']], Tags=[{"Key": k, "Value": tags[k]} for k in tags])

    def _destroy(self):
        if self.state != self.UP: return
        self.log("detaching vpn gateway {0} from vpc {1}".format(self._state['vpnGatewayId'], self._state['vpcId']))
        try:
            self.get_client().detach_vpn_gateway(
                VpcId=self._state['vpcId'],
                VpnGatewayId=self._state['vpnGatewayId'])
        except botocore.exceptions.ClientError as e:
            if e.response['Error']['Code'] == "InvalidVpnGatewayAttachment.NotFound":
                self.warn("VPN gateway '{0}' attachment with VPC '{1}' is invalid".format(
                    self._state['vpnGatewayId'], self._state['vpcId']))
            else:
                raise e

        # TODO delete VPN connections associated with this VPN gtw
        self.log("deleting vpn gateway {}".format(self._state['vpnGatewayId']))
        try:
            self.get_client().delete_vpn_gateway(
                VpnGatewayId=self._state['vpnGatewayId'])
        except botocore.exceptions.ClientError as e:
            if e.response['Error']['Code'] == "InvalidVpnGatewayID.NotFound":
                self.warn("VPN gateway {} was already deleted".format(self._state['vpnGatewayId']))
            else:
                raise e

        with self.depl._db:
            self.state = self.MISSING
            self._state['region'] = None
            self._state['vpnGatewayId'] = None
            self._state['vpcId'] = None
            self._state['zone'] = None

    def destroy(self, wipe=False):
        self._destroy()
        return True
Exemplo n.º 39
0
class VPCEndpointState(nixops.resources.DiffEngineResourceState, EC2CommonState):
    """State of a VPC endpoint."""
    state = nixops.util.attr_property("state", nixops.resources.DiffEngineResourceState.MISSING, int)
    access_key_id = nixops.util.attr_property("accessKeyId", None)
    _reserved_keys = EC2CommonState.COMMON_EC2_RESERVED + ["endpointId","creationToken"]

    def __init__(self, depl, name, id):
        nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
        self._state = StateDict(depl, id)
        self.handle_create_endpoint = Handler(['region', 'serviceName', 'vpcId'], handle=self.realize_create_endpoint)
        self.handle_modify_endpoint = Handler(['policy', 'routeTableIds'],
                after=[self.handle_create_endpoint],
                handle=self.realize_modify_endpoint)

    @classmethod
    def get_type(cls):
        return "vpc-endpoint"

    def show_type(self):
        s = super(VPCEndpointState, self).show_type()
        if self._state.get('region', None): s = "{0} [{1}]".format(s, self._state['region'])
        return s

    @property
    def resource_id(self):
        return self._state.get('endpointId', None)

    def prefix_definition(self, attr):
        return {('resources', 'vpcEndpoints'): attr}

    def get_defintion_prefix(self):
        return "resources.vpcEndpoints"

    def create_after(self, resources, defn):
        return {r for r in resources if
                isinstance(r, nixops.resources.vpc.VPCState) or
                isinstance(r, nixops.resources.vpc_route_table.VPCRouteTableState)}

    def realize_create_endpoint(self, allow_recreate):
        config = self.get_defn()
        if self.state == self.UP:
            if not allow_recreate:
                raise Exception("vpc endpoint {} definition changed"
                                " use --allow-recreate if you want to create a new one".format(
                                    self._state['endpointId']))
            self.warn("vpc endpoint changed, recreating...")
            self._destroy()

        self._state['region'] = config['region']

        vpc_id = config['vpcId']

        if vpc_id.startswith("res-"):
            res = self.depl.get_typed_resource(vpc_id[4:].split(".")[0], "vpc")
            vpc_id = res._state["vpcId"]

        if not self._state.get('creationToken', None):
            self._state['creationToken'] = str(uuid.uuid4())
            self.state = self.STARTING

        response = self.get_client().create_vpc_endpoint(
            ClientToken=self._state['creationToken'],
            ServiceName=config['serviceName'],
            VpcId=vpc_id)

        endpoint_id = response['VpcEndpoint']['VpcEndpointId']
        with self.depl._db:
            self.state = self.UP
            self._state['endpointId'] = endpoint_id
            self._state['vpcId'] = vpc_id
            self._state['serviceName'] = config['serviceName']

    def realize_modify_endpoint(self, allow_recreate):
        config = self.get_defn()
        old_rtbs = self._state.get('routeTableIds', [])
        new_rtbs = []
        for rtb in config["routeTableIds"]:
            if rtb.startswith("res-"):
               res = self.depl.get_typed_resource(rtb[4:].split(".")[0], "vpc-route-table")
               new_rtbs.append(res._state['routeTableId'])
            else:
               new_rtbs.append(rtb)

        to_remove = [r for r in old_rtbs if r not in new_rtbs]
        to_add = [r for r in new_rtbs if r not in old_rtbs]

        edp_input = dict()
        edp_input['AddRouteTableIds'] = to_add
        edp_input['RemoveRouteTableIds'] = to_remove
        if config['policy'] is not None: edp_input['PolicyDocument']
        edp_input['VpcEndpointId'] = self._state['endpointId']

        self.get_client().modify_vpc_endpoint(**edp_input)

        with self.depl._db:
            self._state['policy'] = config['policy']
            self._state['routeTableIds'] = new_rtbs

    def _destroy(self):
        if self.state != self.UP: return
        try:
            self.log("deleting vpc endpoint {}".format(self._state['endpointId']))
            self.get_client().delete_vpc_endpoints(VpcEndpointIds=[self._state['endpointId']])
        except botocore.exceptions.ClientError as e:
            if e.response['Error']['Code'] == 'InvalidVpcEndpointId.NotFound':
                self.warn("vpc endpoint {} was already deleted".format(self._state['endpointId']))
            else:
                raise e

        with self.depl._db:
            self.state = self.MISSING
            self._state['endpointId'] = None
            self._state['vpcId'] = None
            self._state['serviceName'] = None
            self._state['policy'] = None
            self._state['routeTableIds'] = None

    def destroy(self, wipe=False):
        self._destroy()
        return True
Exemplo n.º 40
0
class VPCNatGatewayState(nixops.resources.DiffEngineResourceState, EC2CommonState):
    """State of a VPC NAT gateway"""

    state = nixops.util.attr_property("state", nixops.resources.DiffEngineResourceState.MISSING, int)
    access_key_id = nixops.util.attr_property("accessKeyId", None)
    _reserved_keys = EC2CommonState.COMMON_EC2_RESERVED + ['natGatewayId', 'creationToken']

    @classmethod
    def get_type(cls):
        return "vpc-nat-gateway"

    def __init__(self, depl, name, id):
        nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
        self._state = StateDict(depl, id)
        self.region = self._state.get('region', None)
        self.handle_create_gtw = Handler(['region', 'subnetId', 'allocationId'], handle=self.realize_create_gtw)
        self.nat_gtw_id = self._state.get('natGatewayId', None)

    def show_type(self):
        s = super(VPCNatGatewayState, self).show_type()
        if self.region: s = "{0} [{1}]".format(s, self.region)
        return s

    @property
    def resource_id(self):
        return self._state.get('natGatewayId', None)

    def prefix_definition(self, attr):
        return {('resources', 'vpcNatGateways'): attr}

    def get_physical_spec(self):
        return { 'natGatewayId': self._state.get('natGatewayId', None) }

    def get_definition_prefix(self):
        return "resources.vpcNatGateways."

    def create_after(self, resources, defn):
        return {r for r in resources if
                isinstance(r, nixops.resources.vpc_subnet.VPCSubnetState) or
                isinstance(r, nixops.resources.elastic_ip.ElasticIPState)}

    def realize_create_gtw(self, allow_recreate):
        config = self.get_defn()
        if self.state == self.UP:
            if not allow_recreate:
                raise Exception("nat gateway {} defintion changed"
                                " use --allow-recreate if you want to create a new one".format(
                                    self._state['natGatewayId']))
            self.warn("nat gateway changed, recreating...")
            self._destroy()

        self._state['region'] = config['region']

        subnet_id = config['subnetId']
        allocation_id = config['allocationId']

        if allocation_id.startswith("res-"):
            res = self.depl.get_typed_resource(allocation_id[4:].split(".")[0], "elastic-ip")
            allocation_id = res.allocation_id

        if subnet_id.startswith("res-"):
            res = self.depl.get_typed_resource(subnet_id[4:].split(".")[0], "vpc-subnet")
            subnet_id = res._state['subnetId']

        if not self._state.get('creationToken', None):
            self._state['creationToken'] = str(uuid.uuid4())
            self.state = self.STARTING

        response = self.get_client().create_nat_gateway(ClientToken=self._state['creationToken'], AllocationId=allocation_id,
                                                   SubnetId=subnet_id)

        gtw_id = response['NatGateway']['NatGatewayId']
        with self.depl._db:
            self.state = self.UP
            self._state['subnetId'] = subnet_id
            self._state['allocationId'] = allocation_id
            self._state['natGatewayId'] = gtw_id

    def wait_for_nat_gtw_deletion(self):
        self.log("waiting for nat gateway {0} to be deleted".format(self._state['natGatewayId']))
        while True:
            try:
                response = self.get_client().describe_nat_gateways(
                    NatGatewayIds=[self._state['natGatewayId']]
                    )
            except botocore.exceptions.ClientError as e:
                if e.response['Error']['Code'] == "InvalidNatGatewayID.NotFound" or e.response['Error']['Code'] == "NatGatewayNotFound":
                    self.warn("nat gateway {} was already deleted".format(self._state['natGatewayId']))
                    break
                else:
                    raise
            if len(response['NatGateways'])==1:
                if response['NatGateways'][0]['State'] == "deleted":
                    break
                elif response['NatGateways'][0]['State'] != "deleting":
                    raise Exception("nat gateway {0} in an unexpected state {1}".format(
                        self._state['natGatewayId'], response['NatGateways'][0]['State']))
                self.log_continue(".")
                time.sleep(1)
            else:
                break
        self.log_end(" done")

    def _destroy(self):
        if self.state == self.UP:
            self.log("deleting vpc NAT gateway {}".format(self._state['natGatewayId']))
            try:
                self.get_client().delete_nat_gateway(NatGatewayId=self._state['natGatewayId'])
                with self.depl._db: self.state = self.STOPPING
            except botocore.exceptions.ClientError as e:
                if e.response['Error']['Code'] == "InvalidNatGatewayID.NotFound" or e.response['Error']['Code'] == "NatGatewayNotFound":
                    self.warn("nat gateway {} was already deleted".format(self._state['natGatewayId']))
                else:
                    raise e

        if self.state == self.STOPPING:
            self.wait_for_nat_gtw_deletion()

        with self.depl._db:
            self.state = self.MISSING
            self._state['region'] = None
            self._state['subnetId'] = None
            self._state['allocationId'] = None
            self._state['natGatewayId'] = None

    def destroy(self, wipe=False):
        self._destroy()
        return True
class AWSVPNConnectionRouteState(nixops.resources.DiffEngineResourceState,
                                 EC2CommonState):
    """State of a VPN connection route"""

    state = nixops.util.attr_property(
        "state", nixops.resources.DiffEngineResourceState.MISSING, int)
    access_key_id = nixops.util.attr_property("accessKeyId", None)
    _reserved_keys = EC2CommonState.COMMON_EC2_RESERVED

    @classmethod
    def get_type(cls):
        return "aws-vpn-connection-route"

    def __init__(self, depl, name, id):
        nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
        self._state = StateDict(depl, id)
        self.region = self._state.get("region", None)
        self.handle_create_vpn_route = Handler(
            ["region", "vpnConnectionId", "destinationCidrBlock"],
            handle=self.realize_create_vpn_route,
        )

    def show_type(self):
        s = super(AWSVPNConnectionRouteState, self).show_type()
        if self.region:
            s = "{0} [{1}]".format(s, self.region)
        return s

    @property
    def resource_id(self):
        return self._state.get("destinationCidrBlock", None)

    def prefix_definition(self, attr):
        return {("resources", "awsVPNConnectionRoutes"): attr}

    def get_definition_prefix(self):
        return "resources.awsVPNConnectionRoutes."

    def create_after(self, resources, defn):
        return {
            r
            for r in resources
            if isinstance(r, aws_vpn_connection.AWSVPNConnectionState)
        }

    def realize_create_vpn_route(self, allow_recreate):
        config = self.get_defn()

        if self.state == self.UP:
            if not allow_recreate:
                raise Exception(
                    "vpn connection route {} definition changed and it needs to be recreated"
                    " use --allow-recreate if you want to create a new one".
                    format(self.name))
            self.warn("route definition changed, recreating ...")
            self._destroy()

        self._state["region"] = config["region"]
        vpn_conn_id = config["vpnConnectionId"]
        if vpn_conn_id.startswith("res-"):
            res = self.depl.get_typed_resource(
                vpn_conn_id[4:].split(".")[0],
                "aws-vpn-connection",
                AWSVPNConnectionState,
            )
            vpn_conn_id = res._state["vpnConnectionId"]

        self.log("creating route to {0} using vpn connection {1}".format(
            config["destinationCidrBlock"], vpn_conn_id))
        self.get_client().create_vpn_connection_route(
            DestinationCidrBlock=config["destinationCidrBlock"],
            VpnConnectionId=vpn_conn_id,
        )

        with self.depl._db:
            self.state = self.UP
            self._state["vpnConnectionId"] = vpn_conn_id
            self._state["destinationCidrBlock"] = config[
                "destinationCidrBlock"]

    def _destroy(self):
        if self.state != self.UP:
            return
        self.log("deleting route to {}".format(
            self._state["destinationCidrBlock"]))
        try:
            self.get_client().delete_vpn_connection_route(
                DestinationCidrBlock=self._state["destinationCidrBlock"],
                VpnConnectionId=self._state["vpnConnectionId"],
            )
        except botocore.exceptions.ClientError as e:
            if (e.response["Error"]["Code"] == "InvalidRoute.NotFound"
                    or e.response["Error"]["Code"]
                    == "InvalidVpnConnectionID.NotFound"):
                self.warn("route or vpn connection was already deleted")
            else:
                raise e

        with self.depl._db:
            self.state = self.MISSING
            self._state["vpnConnectionId"] = None
            self._state["destinationCidrBlock"] = None

    def destroy(self, wipe=True):
        self._destroy()
        return True
class VPCRouteTableAssociationState(nixops.resources.DiffEngineResourceState, EC2CommonState):
    """State of a VPC route table association"""

    state = nixops.util.attr_property("state", nixops.resources.DiffEngineResourceState.MISSING, int)
    access_key_id = nixops.util.attr_property("accessKeyId", None)
    _reserved_keys = EC2CommonState.COMMON_EC2_RESERVED + ['associationId']

    @classmethod
    def get_type(cls):
        return "vpc-route-table-association"

    def __init__(self, depl, name, id):
        nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
        self._state = StateDict(depl, id)
        self.region = self._state.get('region', None)
        self.handle_associate_route_table = Handler(['region', 'routeTableId', 'subnetId'], handle=self.realize_associate_route_table)

    def show_type(self):
        s = super(VPCRouteTableAssociationState, self).show_type()
        if self.region: s = "{0} [{1}]".format(s, self.region)
        return s

    @property
    def resource_id(self):
        return self._state.get('associationId', None)

    def prefix_definition(self, attr):
        return {('resources', 'vpcRouteTableAssociations'): attr}

    def get_physical_spec(self):
        return { 'associationId': self._state.get('associationId', None) }

    def get_definition_prefix(self):
        return "resources.vpcRouteTableAssociations."

    def create_after(self, resources, defn):
        return {r for r in resources if
                isinstance(r, nixops.resources.vpc_route_table.VPCRouteTableState)}

    def realize_associate_route_table(self, allow_recreate):
        config = self.get_defn()

        if self.state == self.UP:
            if not allow_recreate:
                raise Exception("route table association {} definition changed and it needs to be recreated"
                                " use --allow-recreate if you want to create a new one".format(self._state['associationId']))
            self.warn("route table association definition changed, recreating ...")
            self._destroy()

        self._state['region'] = config['region']

        route_table_id = config['routeTableId']
        if route_table_id.startswith("res-"):
            res = self.depl.get_typed_resource(route_table_id[4:].split(".")[0], "vpc-route-table")
            route_table_id = res._state['routeTableId']

        subnet_id = config['subnetId']
        if subnet_id.startswith("res-"):
            res = self.depl.get_typed_resource(subnet_id[4:].split(".")[0], "vpc-subnet")
            subnet_id = res._state['subnetId']

        self.log("associating route table {0} to subnet {1}".format(route_table_id, subnet_id))
        association = self.get_client().associate_route_table(RouteTableId=route_table_id,
                                                         SubnetId=subnet_id)

        with self.depl._db:
            self.state = self.UP
            self._state['routeTableId'] = route_table_id
            self._state['subnetId'] = subnet_id
            self._state['associationId'] = association['AssociationId']

    def _destroy(self):
        if self.state != self.UP: return
        self.log("disassociating route table {0} from subnet {1}".format(self._state['routeTableId'], self._state['subnetId']))
        try:
            self.get_client().disassociate_route_table(AssociationId=self._state['associationId'])
        except botocore.exceptions.ClientError as error:
            if error.response['Error']['Code'] == "InvalidAssociationID.NotFound":
                self.warn("route table {} was already deleted".format(self._state['associationId']))
            else:
                raise error

        with self.depl._db:
            self.state = self.MISSING
            self._state['routeTableId'] = None
            self._state['subnetId'] = None
            self._state['associationId'] = None

    def destroy(self, wipe=False):
        self._destroy()
        return True
Exemplo n.º 43
0
class VPCNatGatewayState(nixops.resources.DiffEngineResourceState,
                         EC2CommonState):
    """State of a VPC NAT gateway"""

    state = nixops.util.attr_property(
        "state", nixops.resources.DiffEngineResourceState.MISSING, int)
    access_key_id = nixops.util.attr_property("accessKeyId", None)
    _reserved_keys = EC2CommonState.COMMON_EC2_RESERVED + [
        'natGatewayId', 'creationToken'
    ]

    @classmethod
    def get_type(cls):
        return "vpc-nat-gateway"

    def __init__(self, depl, name, id):
        nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
        self._state = StateDict(depl, id)
        self.region = self._state.get('region', None)
        self.handle_create_gtw = Handler(
            ['region', 'subnetId', 'allocationId'],
            handle=self.realize_create_gtw)
        self.nat_gtw_id = self._state.get('natGatewayId', None)

    def show_type(self):
        s = super(VPCNatGatewayState, self).show_type()
        if self.region: s = "{0} [{1}]".format(s, self.region)
        return s

    @property
    def resource_id(self):
        return self._state.get('natGatewayId', None)

    def prefix_definition(self, attr):
        return {('resources', 'vpcNatGateways'): attr}

    def get_physical_spec(self):
        return {'natGatewayId': self._state.get('natGatewayId', None)}

    def get_definition_prefix(self):
        return "resources.vpcNatGateways."

    def create_after(self, resources, defn):
        return {
            r
            for r in resources
            if isinstance(r, nixopsaws.resources.vpc_subnet.VPCSubnetState)
            or isinstance(r, nixopsaws.resources.elastic_ip.ElasticIPState)
        }

    def realize_create_gtw(self, allow_recreate):
        config = self.get_defn()
        if self.state == self.UP:
            if not allow_recreate:
                raise Exception(
                    "nat gateway {} defintion changed"
                    " use --allow-recreate if you want to create a new one".
                    format(self._state['natGatewayId']))
            self.warn("nat gateway changed, recreating...")
            self._destroy()

        self._state['region'] = config['region']

        subnet_id = config['subnetId']
        allocation_id = config['allocationId']

        if allocation_id.startswith("res-"):
            res = self.depl.get_typed_resource(allocation_id[4:].split(".")[0],
                                               "elastic-ip")
            allocation_id = res.allocation_id

        if subnet_id.startswith("res-"):
            res = self.depl.get_typed_resource(subnet_id[4:].split(".")[0],
                                               "vpc-subnet")
            subnet_id = res._state['subnetId']

        if not self._state.get('creationToken', None):
            self._state['creationToken'] = str(uuid.uuid4())
            self.state = self.STARTING

        response = self.get_client().create_nat_gateway(
            ClientToken=self._state['creationToken'],
            AllocationId=allocation_id,
            SubnetId=subnet_id)

        gtw_id = response['NatGateway']['NatGatewayId']
        with self.depl._db:
            self.state = self.UP
            self._state['subnetId'] = subnet_id
            self._state['allocationId'] = allocation_id
            self._state['natGatewayId'] = gtw_id

    def wait_for_nat_gtw_deletion(self):
        self.log("waiting for nat gateway {0} to be deleted".format(
            self._state['natGatewayId']))
        while True:
            try:
                response = self.get_client().describe_nat_gateways(
                    NatGatewayIds=[self._state['natGatewayId']])
            except botocore.exceptions.ClientError as e:
                if e.response['Error'][
                        'Code'] == "InvalidNatGatewayID.NotFound" or e.response[
                            'Error']['Code'] == "NatGatewayNotFound":
                    self.warn("nat gateway {} was already deleted".format(
                        self._state['natGatewayId']))
                    break
                else:
                    raise
            if len(response['NatGateways']) == 1:
                if response['NatGateways'][0]['State'] == "deleted":
                    break
                elif response['NatGateways'][0]['State'] != "deleting":
                    raise Exception(
                        "nat gateway {0} in an unexpected state {1}".format(
                            self._state['natGatewayId'],
                            response['NatGateways'][0]['State']))
                self.log_continue(".")
                time.sleep(1)
            else:
                break
        self.log_end(" done")

    def _destroy(self):
        if self.state == self.UP:
            self.log("deleting vpc NAT gateway {}".format(
                self._state['natGatewayId']))
            try:
                self.get_client().delete_nat_gateway(
                    NatGatewayId=self._state['natGatewayId'])
                with self.depl._db:
                    self.state = self.STOPPING
            except botocore.exceptions.ClientError as e:
                if e.response['Error'][
                        'Code'] == "InvalidNatGatewayID.NotFound" or e.response[
                            'Error']['Code'] == "NatGatewayNotFound":
                    self.warn("nat gateway {} was already deleted".format(
                        self._state['natGatewayId']))
                else:
                    raise e

        if self.state == self.STOPPING:
            self.wait_for_nat_gtw_deletion()

        with self.depl._db:
            self.state = self.MISSING
            self._state['region'] = None
            self._state['subnetId'] = None
            self._state['allocationId'] = None
            self._state['natGatewayId'] = None

    def destroy(self, wipe=False):
        self._destroy()
        return True
Exemplo n.º 44
0
class VPCDhcpOptionsState(nixops.resources.DiffEngineResourceState,
                          EC2CommonState):
    """State of a VPC DHCP options."""

    definition_type = VPCDhcpOptionsDefinition

    state = nixops.util.attr_property(
        "state", nixops.resources.DiffEngineResourceState.MISSING, int)
    access_key_id = nixops.util.attr_property("accessKeyId", None)
    _reserved_keys = EC2CommonState.COMMON_EC2_RESERVED + ["dhcpOptionsId"]

    @classmethod
    def get_type(cls):
        return "vpc-dhcp-options"

    def __init__(self, depl, name, id):
        nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
        self._state = StateDict(depl, id)
        handled_keys = [
            "region",
            "vpcId",
            "domainNameServers",
            "domainName",
            "ntpServers",
            "netbiosNameServers",
            "netbiosNodeType",
        ]
        self.handle_create_dhcp_options = Handler(
            handled_keys, handle=self.realize_create_dhcp_options)
        self.handle_tag_update = Handler(
            ["tags"],
            after=[self.handle_create_dhcp_options],
            handle=self.realize_update_tag,
        )

    def show_type(self):
        s = super(VPCDhcpOptionsState, self).show_type()
        region = self._state.get("region", None)
        if region:
            s = "{0} [{1}]".format(s, region)
        return s

    @property
    def resource_id(self):
        return self._state.get("dhcpOptionsId", None)

    def prefix_definition(self, attr):
        return {("resources", "vpcDhcpOptions"): attr}

    def get_physical_spec(self):
        return {}

    def get_definition_prefix(self):
        return "resources.vpcDhcpOptions."

    def create_after(self, resources, defn):
        return {r for r in resources if isinstance(r, vpc.VPCState)}

    def get_dhcp_config_option(self, key, values):
        val = values if isinstance(values, list) else [str(values)]
        return {"Key": key, "Values": val}

    def generate_dhcp_configuration(self, config):
        configuration = []

        def check_and_append(option, key):
            if config[option]:
                configuration.append(
                    self.get_dhcp_config_option(key=key,
                                                values=config[option]))

        check_and_append("domainNameServers", "domain-name-servers")
        check_and_append("domainName", "domain-name")
        check_and_append("ntpServers", "ntp-servers")
        check_and_append("netbiosNameServers", "netbios-name-servers")
        check_and_append("netbiosNodeType", "netbios-node-type")
        return configuration

    def realize_create_dhcp_options(self, allow_recreate):
        config: VPCDhcpOptionsDefinition = self.get_defn()
        if self.state == (self.UP or self.STARTING):
            if not allow_recreate:
                raise Exception(
                    "to recreate the dhcp options please add --allow-recreate"
                    " to the deploy command")
            self.warn("the dhcp options {} will be destroyed and re-created")
            self._destroy()

        self._state["region"] = config.config.region
        vpc_id = config.config.vpcId
        if vpc_id.startswith("res-"):
            res = self.depl.get_typed_resource(vpc_id[4:].split(".")[0], "vpc",
                                               VPCState)
            vpc_id = res._state["vpcId"]

        dhcp_config = self.generate_dhcp_configuration(config)

        def create_dhcp_options(dhcp_config):
            self.log("creating dhcp options...")
            response = self.get_client().create_dhcp_options(
                DhcpConfigurations=dhcp_config)
            return response.get("DhcpOptions").get("DhcpOptionsId")

        dhcp_options_id = create_dhcp_options(dhcp_config)
        with self.depl._db:
            self.state = self.STARTING
            self._state["vpcId"] = vpc_id
            self._state["dhcpOptionsId"] = dhcp_options_id
            self._state["domainName"] = config.config.domainName
            self._state["domainNameServers"] = config.config.domainNameServers
            self._state["ntpServers"] = config.config.ntpServers
            self._state[
                "netbiosNameServers"] = config.config.netbiosNameServers
            self._state["netbiosNodeType"] = config.config.netbiosNodeType

        self.get_client().associate_dhcp_options(DhcpOptionsId=dhcp_options_id,
                                                 VpcId=vpc_id)
        with self.depl._db:
            self.state = self.UP

    def realize_update_tag(self, allow_recreate):
        config: VPCDhcpOptionsDefinition = self.get_defn()
        tags = {k: v for k, v in config.config.tags.items()}
        tags.update(self.get_common_tags())
        self.get_client().create_tags(
            Resources=[self._state["dhcpOptionsId"]],
            Tags=[{
                "Key": k,
                "Value": tags[k]
            } for k in tags],
        )

    def _destroy(self):
        if self.state != self.UP:
            return
        dhcp_options_id = self._state.get("dhcpOptionsId", None)
        if dhcp_options_id:
            self.log("deleting dhcp options {0}".format(dhcp_options_id))
            try:
                self.get_client().associate_dhcp_options(
                    DhcpOptionsId="default", VpcId=self._state["vpcId"])
                self.get_client().delete_dhcp_options(
                    DhcpOptionsId=dhcp_options_id)
            except botocore.exceptions.ClientError as e:
                if e.response["Error"][
                        "Code"] == "InvalidDhcpOptionsID.NotFound":
                    self.warn("dhcp options {0} was already deleted".format(
                        dhcp_options_id))
                else:
                    raise e

            with self.depl._db:
                self.state = self.MISSING
                self._state["vpcId"] = None
                self._state["dhcpOptions"] = None
                self._state["domainName"] = None
                self._state["domainNameServers"] = None
                self._state["ntpServers"] = None
                self._state["netbiosNameServers"] = None
                self._state["netbiosNodeType"] = None

    def destroy(self, wipe=False):
        self._destroy()
        return True
Exemplo n.º 45
0
class VPCEgressOnlyInternetGatewayState(nixops.resources.DiffEngineResourceState, EC2CommonState):
    """State of a VPC egress only internet gateway."""
    state = nixops.util.attr_property("state", nixops.resources.DiffEngineResourceState.MISSING, int)
    access_key_id = nixops.util.attr_property("accessKeyId", None)
    _reserved_keys = EC2CommonState.COMMON_EC2_RESERVED + ["egressOnlyInternetGatewayId"]

    def __init__(self, depl, name, id):
        nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
        self._state = StateDict(depl, id)
        self.handle_create_igw = Handler(['region', 'vpcId'], handle=self.realize_create_gtw)

    @classmethod
    def get_type(cls):
        return "vpc-egress-only-internet-gateway"

    def show_type(self):
        s = super(VPCEgressOnlyInternetGatewayState, self).show_type()
        if self._state.get('region', None): s = "{0} [{1}]".format(s, self._state['region'])
        return s

    @property
    def resource_id(self):
        return self._state.get('egressOnlyInternetGatewayId', None)

    def prefix_definition(self, attr):
        return {('resources', 'vpcEgressOnlyInternetGateways'): attr}

    def get_defintion_prefix(self):
        return "resources.vpcEgressOnlyInternetGateways."

    def create_after(self, resources, defn):
        return {r for r in resources if
                isinstance(r, nixopsaws.resources.vpc.VPCState) or
                isinstance(r, nixopsaws.resources.elastic_ip.ElasticIPState)}

    def realize_create_gtw(self, allow_recreate):
        config = self.get_defn()

        if self.state == self.UP:
            if not allow_recreate:
                raise Exception("egress only internet gateway {} defintion changed"
                                " use --allow-recreate if you want to create a new one".format(
                                    self._state['egressOnlyInternetGatewayId']))
            self.warn("egress only internet gateway changed, recreating...")
            self._destroy()

        self._state['region'] = config['region']

        vpc_id = config['vpcId']
        if vpc_id.startswith("res-"):
            res = self.depl.get_typed_resource(vpc_id[4:].split(".")[0], "vpc")
            vpc_id = res._state['vpcId']

        self.log("creating egress only internet gateway in region {0}, vpc {1}".format(self._state['region'], vpc_id))
        response = self.get_client().create_egress_only_internet_gateway(VpcId=vpc_id)
        igw_id = response['EgressOnlyInternetGateway']['EgressOnlyInternetGatewayId']

        with self.depl._db:
            self.state = self.UP
            self._state['region'] = config['region']
            self._state['vpcId'] = vpc_id
            self._state['egressOnlyInternetGatewayId'] = igw_id

    def _destroy(self):
        if self.state != self.UP: return
        self.log("deleting egress only internet gateway {0}".format(self._state['egressOnlyInternetGatewayId']))
        self.get_client().delete_egress_only_internet_gateway(EgressOnlyInternetGatewayId=self._state['egressOnlyInternetGatewayId'])

        with self.depl._db:
            self.state = self.MISSING
            self._state['region'] = None
            self._state['vpcId'] = None
            self._state['egressOnlyInternetGatewayId'] = None

    def destroy(self, wipe=False):
        self._destroy()
        return True
Exemplo n.º 46
0
class VPCNetworkInterfaceState(nixops.resources.DiffEngineResourceState, EC2CommonState):
    """State of a VPC network interface"""

    state = nixops.util.attr_property("state", nixops.resources.DiffEngineResourceState.MISSING, int)
    access_key_id = nixops.util.attr_property("accessKeyId", None)
    _reserved_keys = EC2CommonState.COMMON_EC2_RESERVED + ['networkInterfaceId']

    @classmethod
    def get_type(cls):
        return "vpc-network-interface"

    def __init__(self, depl, name, id):
        nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
        self._state = StateDict(depl, id)
        self.region = self._state.get('region', None)
        self.handle_create_eni = Handler(['region', 'subnetId', 'primaryPrivateIpAddress',
                                          'privateIpAddresses', 'secondaryPrivateIpAddressCount'],
                                          handle=self.realize_create_eni)
        self.handle_modify_eni_attrs = Handler(['description', 'securityGroups', 'sourceDestCheck'],
                                               handle=self.realize_modify_eni_attrs,
                                               after=[self.handle_create_eni])
        self.handle_tag_update = Handler(['tags'], after=[self.handle_create_eni], handle=self.realize_update_tag)

    def show_type(self):
        s = super(VPCNetworkInterfaceState, self).show_type()
        if self.region: s = "{0} [{1}]".format(s, self.region)
        return s

    @property
    def resource_id(self):
        return self._state.get('networkInterfaceId', None)

    def prefix_definition(self, attr):
        return {('resources', 'vpcNetworkInterfaces'): attr}

    def get_physical_spec(self):
        return { 'networkInterfaceId': self._state.get('networkInterfaceId', None) }

    def get_definition_prefix(self):
        return "resources.vpcNetworkInterfaces."

    def create_after(self, resources, defn):
        return {r for r in resources if
                isinstance(r, nixops.resources.vpc_subnet.VPCSubnetState)}

    def realize_create_eni(self, allow_recreate):
        config = self.get_defn()
        if self.state == self.UP:
            if not allow_recreate:
                raise Exception("network interface {} definition changed and it needs to be recreated"
                                " use --allow-recreate if you want to create a new one".format(self._state['networkInterfaceId']))
            self.warn("network interface definition changed, recreating ...")
            self._destroy()

        self._state['region'] = config['region']

        eni_input = self.network_interface_input(config)
        self.log("creating vpc network interface under {}".format(eni_input['SubnetId']))
        response = self.get_client().create_network_interface(**eni_input)

        eni = response['NetworkInterface']

        def split_ips(eni_ips):
            seconday = []
            for ip in eni_ips:
                if ip['Primary']:
                    primary = ip['PrivateIpAddress']
                else:
                    seconday.append(ip['PrivateIpAddress'])
            return primary, seconday

        primary, secondary = split_ips(eni['PrivateIpAddresses'])

        with self.depl._db:
            self.state = self.UP
            self._state['subnetId'] = eni_input['SubnetId']
            self._state['networkInterfaceId'] = eni['NetworkInterfaceId']
            self._state['primaryPrivateIpAddress'] = primary
            self._state['privateIpAddresses'] = secondary
            self._state['secondaryPrivateIpAddressCount'] = config['secondaryPrivateIpAddressCount']

    def network_interface_input(self, config):
        subnet_id = config['subnetId']
        if subnet_id.startswith("res-"):
            res = self.depl.get_typed_resource(subnet_id[4:].split(".")[0], "vpc-subnet")
            subnet_id = res._state['subnetId']

        groups = []
        for grp in config['securityGroups']:
            if grp.startswith("res-"):
                res = self.depl.get_typed_resource(grp[4:].split(".")[0], "ec2-security-group")
                assert res.vpc_id
                groups.append(res.security_group_id)
            else:
                groups.append(grp)

        primary_ip = config['primaryPrivateIpAddress']
        secondary_private_ips = config['privateIpAddresses']
        secondary_ip_count = config['secondaryPrivateIpAddressCount']
        if (primary_ip and len(secondary_private_ips) > 0) and secondary_ip_count:
            raise Exception("you can't set privateIpAddresses/primaryPrivateIpAddress options together"
                            " with secondaryPrivateIpAddressCount")
        ips = []
        if primary_ip:
            ips.append({'Primary':True, 'PrivateIpAddress':primary_ip})
        if len(secondary_private_ips) > 0:
            for ip in secondary_private_ips:
                ips.append({'Primary':False, 'PrivateIpAddress':ip})

        cfg = dict()
        cfg['Description'] = config['description']
        cfg['Groups'] = groups
        cfg['SubnetId'] = subnet_id
        if not secondary_ip_count:
            cfg['PrivateIpAddresses'] = ips
        else:
            cfg['secondaryPrivateIpAddressCount'] = secondary_ip_count

        return cfg

    def realize_modify_eni_attrs(self, allow_recreate):
        config = self.get_defn()
        self.log("applying network interface attribute changes")
        self.get_client().modify_network_interface_attribute(NetworkInterfaceId=self._state['networkInterfaceId'],
                                                        Description={'Value':config['description']})
        groups = []
        for grp in config['securityGroups']:
            if grp.startswith("res-"):
                res = self.depl.get_typed_resource(grp[4:].split(".")[0], "ec2-security-group")
                assert res.vpc_id
                groups.append(res.security_group_id)
            else:
                groups.append(grp)

        if len(groups) >= 1:
            self.get_client().modify_network_interface_attribute(
                NetworkInterfaceId=self._state['networkInterfaceId'],
                Groups=groups)

        self.get_client().modify_network_interface_attribute(NetworkInterfaceId=self._state['networkInterfaceId'],
                                                        SourceDestCheck={
                                                            'Value':config['sourceDestCheck']
                                                            })
        with self.depl._db:
            self._state['description'] = config['description']
            self._state['securityGroups'] = groups
            self._state['sourceDestCheck'] = config['sourceDestCheck']

    def realize_update_tag(self, allow_recreate):
        config = self.get_defn()
        tags = config['tags']
        tags.update(self.get_common_tags())
        self.get_client().create_tags(Resources=[self._state['networkInterfaceId']], Tags=[{"Key": k, "Value": tags[k]} for k in tags])

    def _destroy(self):
        if self.state != self.UP: return
        self.log("deleting vpc network interface {}".format(self._state['networkInterfaceId']))
        try:
            self.get_client().delete_network_interface(NetworkInterfaceId=self._state['networkInterfaceId'])
        except botocore.exceptions.ClientError as e:
            if e.response['Error']['Code'] == "InvalidNetworkInterfaceID.NotFound":
                self.warn("network interface {} was already deleted".format(self._state['networkInterfaceId']))
            else:
                raise e

        with self.depl._db:
            self.state = self.MISSING
            self._state['networkInterfaceId'] = None
            self._state['primaryPrivateIpAddress'] = None
            self._state['privateIpAddresses'] = None
            self._state['secondaryPrivateIpAddressCount'] = None

    def destroy(self, wipe=False):
        self._destroy()
        return True
Exemplo n.º 47
0
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.handle_create_customer_gtw = Handler(['region', 'publicIp', 'bgpAsn', 'type'], handle=self.realize_create_customer_gtw)
     self.handle_tag_update = Handler(['tags'], after=[self.handle_create_customer_gtw], handle=self.realize_update_tag)
Exemplo n.º 48
0
class VPCRouteTableState(nixops.resources.DiffEngineResourceState, EC2CommonState):
    """State of a VPC route table"""

    state = nixops.util.attr_property("state", nixops.resources.DiffEngineResourceState.MISSING, int)
    access_key_id = nixops.util.attr_property("accessKeyId", None)
    _reserved_keys = EC2CommonState.COMMON_EC2_RESERVED + ['routeTableId']

    @classmethod
    def get_type(cls):
        return "vpc-route-table"

    def __init__(self, depl, name, id):
        nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
        self._state = StateDict(depl, id)
        self.region = self._state.get('region', None)
        self.handle_create_route_table = Handler(['region', 'vpcId'], handle=self.realize_create_route_table)
        self.handle_propagate_vpn_gtws = Handler(
            ['propagatingVgws'],
            handle=self.realize_propagate_vpn_gtws,
            after=[self.handle_create_route_table])
        self.handle_tag_update = Handler(['tags'], after=[self.handle_create_route_table], handle=self.realize_update_tag)

    def show_type(self):
        s = super(VPCRouteTableState, self).show_type()
        if self.region: s = "{0} [{1}]".format(s, self.region)
        return s

    @property
    def resource_id(self):
        return self._state.get('routeTableId', None)

    def prefix_definition(self, attr):
        return {('resources', 'vpcRouteTables'): attr}

    def get_physical_spec(self):
        return { 'routeTableId': self._state.get('routeTableId', None) }

    def get_definition_prefix(self):
        return "resources.vpcRouteTables."

    def create_after(self, resources, defn):
        return {r for r in resources if
                isinstance(r, nixops.resources.vpc.VPCState) or
                isinstance(r, nixops.resources.vpc_subnet.VPCSubnetState)}

    def realize_create_route_table(self, allow_recreate):
        config = self.get_defn()

        if self.state == self.UP:
            if not allow_recreate:
                raise Exception("route table {} definition changed and it needs to be recreated"
                                " use --allow-recreate if you want to create a new one".format(self._state['routeTableId']))
            self.warn("route table definition changed, recreating ...")
            self._destroy()

        self._state['region'] = config['region']

        vpc_id = config['vpcId']
        if vpc_id.startswith("res-"):
            res = self.depl.get_typed_resource(vpc_id[4:].split(".")[0], "vpc")
            vpc_id = res._state['vpcId']

        self.log("creating route table in vpc {}".format(vpc_id))
        route_table = self.get_client().create_route_table(VpcId=vpc_id)

        with self.depl._db:
            self.state = self.UP
            self._state['vpcId'] = vpc_id
            self._state['routeTableId'] = route_table['RouteTable']['RouteTableId']

    def realize_propagate_vpn_gtws(self, allow_recreate):
        config = self.get_defn()
        old_vgws = self._state.get('propagatingVgws', [])
        new_vgws = []

        for vgw in config['propagatingVgws']:
            if vgw.startswith("res-"):
                res = self.depl.get_typed_resource(vgw[4:].split(".")[0], "aws-vpn-gateway")
                new_vgws.append(res._state['vpnGatewayId'])
            else:
                new_vgws.append(vgw)

        to_disable = [r for r in old_vgws if r not in new_vgws]
        to_enable = [r for r in new_vgws if r not in old_vgws]

        for vgw in to_disable:
            self.log("disabling virtual gateway route propagation for {}".format(vgw))
            self.get_client().disable_vgw_route_propagation(
                GatewayId=vgw,
                RouteTableId=self._state['routeTableId'])
        for vgw in to_enable:
            self.log("enabling virtual gateway route propagation for {}".format(vgw))
            self.get_client().enable_vgw_route_propagation(
                GatewayId=vgw,
                RouteTableId=self._state['routeTableId'])

        with self.depl._db:
            self._state['propagatingVgws'] = new_vgws

    def realize_update_tag(self, allow_recreate):
        config = self.get_defn()
        tags = config['tags']
        tags.update(self.get_common_tags())
        self.get_client().create_tags(Resources=[self._state['routeTableId']], Tags=[{"Key": k, "Value": tags[k]} for k in tags])

    def _destroy(self):
        if self.state != self.UP: return
        self.log("deleting route table {}".format(self._state['routeTableId']))
        try:
            self.get_client().delete_route_table(RouteTableId=self._state['routeTableId'])
        except botocore.exceptions.ClientError as error:
            if error.response['Error']['Code'] == "InvalidRouteTableID.NotFound":
                self.warn("route table {} was already deleted".format(self._state['routeTableId']))
            else:
                raise error

        with self.depl._db:
            self.state = self.MISSING
            self._state['vpcId'] = None
            self._state['routeTableId'] = None

    def destroy(self, wipe=False):
        self._destroy()
        return True
Exemplo n.º 49
0
class VPCCustomerGatewayState(nixops.resources.DiffEngineResourceState, EC2CommonState):
    """State of a VPC customer gateway."""
    state = nixops.util.attr_property("state", nixops.resources.DiffEngineResourceState.MISSING, int)
    access_key_id = nixops.util.attr_property("accessKeyId", None)
    _reserved_keys = EC2CommonState.COMMON_EC2_RESERVED + ["customerGatewayId"]

    def __init__(self, depl, name, id):
        nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
        self._state = StateDict(depl, id)
        self.handle_create_customer_gtw = Handler(['region', 'publicIp', 'bgpAsn', 'type'], handle=self.realize_create_customer_gtw)
        self.handle_tag_update = Handler(['tags'], after=[self.handle_create_customer_gtw], handle=self.realize_update_tag)

    @classmethod
    def get_type(cls):
        return "vpc-customer-gateway"

    def show_type(self):
        s = super(VPCCustomerGatewayState, self).show_type()
        if self._state.get('region', None): s = "{0} [{1}]".format(s, self._state['region'])
        return s

    @property
    def resource_id(self):
        return self._state.get('customerGatewayId', None)

    def prefix_definition(self, attr):
        return {('resources', 'vpcCustomerGateways'): attr}

    def get_defintion_prefix(self):
        return "resources.vpcCustomerGateways."

    def realize_create_customer_gtw(self, allow_recreate):
        config = self.get_defn()
        if self.state == self.UP:
            if not allow_recreate:
                raise Exception("customer gateway {} defintion changed"
                                " use --allow-recreate if you want to create a new one".format(
                                    self._state['customerGatewayId']))
            self.warn("customer gateway changed, recreating...")
            self._destroy()

        self._state['region'] = config['region']

        self.log("creating customer gateway")
        response = self.get_client().create_customer_gateway(
            BgpAsn=config['bgpAsn'],
            PublicIp=config['publicIp'],
            Type=config['type'])

        customer_gtw_id = response['CustomerGateway']['CustomerGatewayId']
        with self.depl._db: self.state = self.STARTING

        waiter = self.get_client().get_waiter('customer_gateway_available')
        waiter.wait(CustomerGatewayIds=[customer_gtw_id])

        with self.depl._db:
            self.state = self.UP
            self._state['region'] = config['region']
            self._state['customerGatewayId'] = customer_gtw_id
            self._state['bgpAsn'] = config['bgpAsn']
            self._state['publicIp'] = config['publicIp']
            self._state['type'] = config['type']

    def realize_update_tag(self, allow_recreate):
        config = self.get_defn()
        tags = config['tags']
        tags.update(self.get_common_tags())
        self.get_client().create_tags(Resources=[self._state['customerGatewayId']], Tags=[{"Key": k, "Value": tags[k]} for k in tags])

    def _destroy(self):
        if self.state != self.UP: return
        self.log("deleting customer gateway {}".format(self._state['customerGatewayId']))
        try:
            self.get_client().delete_customer_gateway(CustomerGatewayId=self._state['customerGatewayId'])
        except botocore.exceptions.ClientError as e:
            if e.response['Error']['Code'] == "InvalidCustomerGatewayID.NotFound":
                self.warn("customer gateway {} was already deleted".format(self._state['customerGatewayId']))
            else:
                raise e

        #TODO wait for customer gtw to be deleted
        with self.depl._db:
            self.state = self.MISSING
            self._state['region'] = None
            self._state['customerGatewayId'] = None
            self._state['bgpAsn'] = None
            self._state['publicIp'] = None
            self._state['type'] = None

    def destroy(self, wipe=False):
        self._destroy()
        return True
Exemplo n.º 50
0
class VPCRouteState(nixops.resources.DiffEngineResourceState, EC2CommonState):
    """State of a VPC route"""

    state = nixops.util.attr_property("state", nixops.resources.DiffEngineResourceState.MISSING, int)
    access_key_id = nixops.util.attr_property("accessKeyId", None)
    _reserved_keys = EC2CommonState.COMMON_EC2_RESERVED
    TARGETS = ['egressOnlyInternetGatewayId', 'gatewayId', 'instanceId', 'natGatewayId', 'networkInterfaceId']

    @classmethod
    def get_type(cls):
        return "vpc-route"

    def __init__(self, depl, name, id):
        nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
        self._state = StateDict(depl, id)
        self.region = self._state.get('region', None)
        keys = ['region', 'routeTableId', 'destinationCidrBlock', 'destinationIpv6CidrBlock',
                'egressOnlyInternetGatewayId', 'gatewayId', 'instanceId', 'natGatewayId',
                'networkInterfaceId']
        self.handle_create_route = Handler(keys, handle=self.realize_create_route)

    def show_type(self):
        s = super(VPCRouteState, self).show_type()
        if self.region: s = "{0} [{1}]".format(s, self.region)
        return s

    @property
    def resource_id(self):
        return (self._state.get('destinationCidrBlock', None) or self._state.get('destinationIpv6CidrBlock', None))

    def prefix_definition(self, attr):
        return {('resources', 'vpcRoutes'): attr}

    def get_definition_prefix(self):
        return "resources.vpcRoutes."

    def create_after(self, resources, defn):
        return {r for r in resources if
                isinstance(r, nixopsaws.resources.vpc_route_table.VPCRouteTableState) or
                isinstance(r, nixopsaws.resources.vpc_internet_gateway.VPCInternetGatewayState) or
                isinstance(r, nixopsaws.resources.vpc_nat_gateway.VPCNatGatewayState)}

    def realize_create_route(self, allow_recreate):
        config = self.get_defn()

        if self.state == self.UP:
            if not allow_recreate:
                raise Exception("route {} definition changed and it needs to be recreated"
                                " use --allow-recreate if you want to create a new one".format(self.name))
            self.warn("route definition changed, recreating ...")
            self._destroy()

        self._state['region'] = config['region']

        rtb_id = config['routeTableId']
        if rtb_id.startswith("res-"):
            res = self.depl.get_typed_resource(rtb_id[4:].split(".")[0], "vpc-route-table")
            rtb_id = res._state['routeTableId']

        route = dict()
        config = self.get_defn()
        num_targets = 0
        for item in self.TARGETS:
            if config[item]:
                num_targets+=1
                target = item

        if num_targets > 1:
            raise Exception("you should specify only 1 target from {}".format(str(self.TARGETS)))

        if (config['destinationCidrBlock'] is not None) and (config['destinationIpv6CidrBlock'] is not None):
            raise Exception("you can't set both destinationCidrBlock and destinationIpv6CidrBlock in one route")

        if config['destinationCidrBlock'] is not None: destination = 'destinationCidrBlock'
        if config['destinationIpv6CidrBlock'] is not None: destination = 'destinationIpv6CidrBlock'

        def retrieve_defn(option):
            cfg = config[option]
            if cfg.startswith("res-"):
                name = cfg[4:].split(".")[0]
                res_type = cfg.split(".")[1]
                attr = cfg.split(".")[2] if len(cfg.split(".")) > 2 else option
                res = self.depl.get_typed_resource(name, res_type)
                return res._state[attr]
            else:
                return cfg

        route['RouteTableId'] = rtb_id
        route[self.upper(target)] = retrieve_defn(target)
        route[self.upper(destination)] = config[destination]

        self.log("creating route {0} => {1} in route table {2}".format(retrieve_defn(target), config[destination], rtb_id))
        self.get_client().create_route(**route)

        with self.depl._db:
            self.state = self.UP
            self._state[target] = route[self.upper(target)]
            self._state[destination] = config[destination]
            self._state['routeTableId'] = rtb_id

    def upper(self, option):
        return "%s%s" % (option[0].upper(), option[1:])

    def _destroy(self):
        if self.state != self.UP: return
        destination = 'destinationCidrBlock' if ('destinationCidrBlock' in self._state.keys()) else 'destinationIpv6CidrBlock'
        self.log("deleting route to {0} from route table {1}".format(self._state[destination], self._state['routeTableId']))
        try:
            args = dict()
            args[self.upper(destination)] = self._state[destination]
            args['RouteTableId'] = self._state['routeTableId']
            self.get_client().delete_route(**args)
        except botocore.exceptions.ClientError as error:
            if error.response['Error']['Code'] == "InvalidRoute.NotFound":
                self.warn("route was already deleted")
            else:
                raise error

        with self.depl._db:
            self.state = self.MISSING
            self._state['routeTableId'] = None
            self._state[destination] = None
            for target in self.TARGETS:
                self._state[target] = None

    def destroy(self, wipe=False):
        self._destroy()
        return True
Exemplo n.º 51
0
class VPCNetworkAclstate(nixops.resources.DiffEngineResourceState, EC2CommonState):
    """state of a vpc Network ACL."""

    state = nixops.util.attr_property("state", nixops.resources.DiffEngineResourceState.MISSING, int)
    access_key_id = nixops.util.attr_property("accessKeyId", None)
    _reserved_keys = EC2CommonState.COMMON_EC2_RESERVED + ['networkAclId']

    @classmethod
    def get_type(cls):
        return "vpc-network-acl"

    def __init__(self, depl, name, id):
        nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
        self._state = StateDict(depl, id)
        self.network_acl_id = self._state.get('networkAclId', None)
        self.handle_create_network_acl = Handler(['region', 'vpcId'], handle=self.realize_create_network_acl)
        self.handle_entries = Handler(['entries'], after=[self.handle_create_network_acl]
                                      , handle=self.realize_entries_change)
        self.handle_subnet_association = Handler(['subnetIds'], after=[self.handle_create_network_acl]
                                                 , handle=self.realize_subnets_change)
        self.handle_tag_update = Handler(['tags'], after=[self.handle_create_network_acl], handle=self.realize_update_tag)

    def show_type(self):
        s = super(VPCNetworkAclstate, self).show_type()
        if self._state.get('region', None): s = "{0} [{1}]".format(s, self._state['region'])
        return s

    @property
    def resource_id(self):
        return self.network_acl_id

    def prefix_definition(self, attr):
        return {('resources', 'vpcNetworkAcls'): attr}

    def get_definition_prefix(self):
        return "resources.vpcNetworkAcls."

    def create_after(self, resources, defn):
        return {r for r in resources if
                isinstance(r, nixops.resources.vpc.VPCState) or
                isinstance(r, nixops.resources.vpc_subnet.VPCSubnetState)}

    def realize_create_network_acl(self, allow_recreate):
        config = self.get_defn()
        if self.state == self.UP:
            if not allow_recreate:
                raise Exception("network ACL {} definition changed and it needs to be recreated"
                                " use --allow-recreate if you want to create a new one".format(self.network_acl_id))
            self.warn("network ACL definition changed, recreating ...")
            self._destroy()

        self._state['region'] = config['region']

        vpc_id = config['vpcId']

        if vpc_id.startswith("res-"):
            res = self.depl.get_typed_resource(vpc_id[4:].split(".")[0], "vpc")
            vpc_id = res._state['vpcId']

        self.log("creating network ACL in vpc {}".format(vpc_id))
        response = self.get_client().create_network_acl(VpcId=vpc_id)
        self.network_acl_id = response['NetworkAcl']['NetworkAclId']

        with self.depl._db:
            self.state = self.UP
            self._state['vpcId'] = vpc_id
            self._state['networkAclId'] = self.network_acl_id

    def realize_entries_change(self, allow_recreate):
        config = self.get_defn()
        old_entries = self._state.get('entries', [])
        new_entries = config['entries']
        to_remove = [e for e in old_entries if e not in new_entries]
        to_create = [e for e in new_entries if e not in old_entries]
        for entry in to_remove:
            try:
                self.get_client().delete_network_acl_entry(NetworkAclId=self.network_acl_id, RuleNumber=entry['ruleNumber'], Egress=entry['egress'])
            except botocore.exceptions.ClientError as e:
                if e.response['Error']['Code'] == "InvalidNetworkAclEntry.NotFound":
                    self.warn("rule {0} was already deleted from network ACL {1}".format(entry['ruleNumber'], self.network_acl_id))
                else:
                    raise e

        for entry in to_create:
            rule = self.process_rule_entry(entry)
            self.get_client().create_network_acl_entry(**rule)
        with self.depl._db:
            self._state['entries'] = config['entries']

    def realize_subnets_change(self, allow_recreate):
        config = self.get_defn()
        old_subnets = self._state.get('subnetIds', [])
        new_subnets = []
        for s in config['subnetIds']:
            if s.startswith("res-"):
                res = self.depl.get_typed_resource(s[4:].split(".")[0], "vpc-subnet")
                new_subnets.append(res._state['subnetId'])
            else:
                new_subnets.append(s)

        vpc_id = config['vpcId']

        if vpc_id.startswith("res-"):
            res = self.depl.get_typed_resource(vpc_id[4:].split(".")[0], "vpc")
            vpc_id = res._state['vpcId']

        subnets_to_remove = [s for s in old_subnets if s not in new_subnets]
        subnets_to_add = [s for s in new_subnets if s not in old_subnets]

        default_network_acl = self.get_default_network_acl(vpc_id)

        for subnet in subnets_to_remove:
            association_id = self.get_network_acl_association(subnet)
            self.log("associating subnet {0} to default network acl {1}".format(subnet, default_network_acl))
            self.get_client().replace_network_acl_association(AssociationId=association_id, NetworkAclId=default_network_acl)

        for subnet in subnets_to_add:
            association_id = self.get_network_acl_association(subnet)
            self.log("associating subnet {0} to network acl {1}".format(subnet, self.network_acl_id))
            self.get_client().replace_network_acl_association(AssociationId=association_id, NetworkAclId=self.network_acl_id)

        with self.depl._db:
            self._state['subnetIds'] = new_subnets

    def get_default_network_acl(self, vpc_id):
        response = self.get_client().describe_network_acls(Filters=[{ "Name": "default", "Values": [ "true" ] },
             { "Name": "vpc-id", "Values": [ vpc_id ]}])
        return response['NetworkAcls'][0]['NetworkAclId']

    def get_network_acl_association(self, subnet_id):
        response = self.get_client().describe_network_acls(Filters=[{"Name": "association.subnet-id", "Values":[ subnet_id ]}])
        for association in  response['NetworkAcls'][0]['Associations']:
            if association['SubnetId'] == subnet_id:
                return association['NetworkAclAssociationId']

    def process_rule_entry(self, entry):
        rule = dict()
        rule['NetworkAclId'] = self.network_acl_id
        rule['Protocol'] = entry['protocol']
        rule['RuleNumber'] = entry['ruleNumber']
        rule['RuleAction'] = entry['ruleAction']
        rule['Egress'] = entry['egress']
        if entry['cidrBlock'] is not None: rule['CidrBlock'] = entry['cidrBlock']
        if entry['ipv6CidrBlock'] is not None: rule['Ipv6CidrBlock'] = entry['ipv6CidrBlock']
        if entry['icmpCode'] and entry['icmpType']:
            rule['IcmpTypeCode'] = {"Type": entry['icmpType'], "Code": entry['icmpCode']}
        if entry['fromPort'] and entry['toPort']:
            rule['PortRange'] = { "From": entry['fromPort'], "To": entry['toPort'] }
        return rule

    def _destroy(self):
        if self.state != self.UP: return
        try:
            subnets = self._state.get('subnetIds', [])
            default_network_acl = self.get_default_network_acl(self._state['vpcId'])
            for subnet in subnets:
                association_id = self.get_network_acl_association(subnet)
                self.log("associating subnet {0} to default network acl {1}".format(subnet, default_network_acl))
                self.get_client().replace_network_acl_association(AssociationId=association_id, NetworkAclId=default_network_acl)
            self.log("deleting network acl {}".format(self.network_acl_id))
            self.get_client().delete_network_acl(NetworkAclId=self.network_acl_id)
        except botocore.exceptions.ClientError as e:
            if e.response['Error']['Code'] == 'InvalidNetworkAclID.NotFound':
                self.warn("network ACL {} was already deleted".format(self.network_acl_id))
            else:
                raise e

        with self.depl._db:
            self.state = self.MISSING
            self._state['networkAclId'] = None
            self._state['region'] = None
            self._state['vpcId'] = None
            self._state['entries'] = None

    def realize_update_tag(self, allow_recreate):
        config = self.get_defn()
        tags = config['tags']
        tags.update(self.get_common_tags())
        self.get_client().create_tags(Resources=[self._state['networkAclId']], Tags=[{"Key": k, "Value": tags[k]} for k in tags])

    def destroy(self, wipe=False):
        self._destroy()
        return True
 def __init__(self, depl, name, id):
     nixops.resources.DiffEngineResourceState.__init__(self, depl, name, id)
     self._state = StateDict(depl, id)
     self.region = self._state.get('region', None)
     self.handle_create_eni_attachment = Handler(['region', 'networkInterfaceId', 'instanceId', 'deviceIndex' ],
                                       handle=self.realize_create_eni_attachment)