from dataclasses import dataclass, field
from typing import List, Optional
from linode_api4.common import Price, RegionPrice
from linode_api4.errors import UnexpectedResponseError
from linode_api4.objects.base import Base, Property
from linode_api4.objects.dbase import DerivedBase
from linode_api4.objects.region import Region
from linode_api4.objects.serializable import JSONObject
[docs]
class IPv6Pool(Base):
"""
DEPRECATED
"""
api_endpoint = "/networking/ipv6/pools/{range}"
id_attribute = "range"
properties = {
"range": Property(identifier=True),
"region": Property(slug_relationship=Region),
}
[docs]
class IPv6Range(Base):
"""
An instance of a Linode IPv6 Range.
API Documentation: https://techdocs.akamai.com/linode-api/reference/get-ipv6-range
"""
api_endpoint = "/networking/ipv6/ranges/{range}"
id_attribute = "range"
properties = {
"range": Property(identifier=True),
"region": Property(slug_relationship=Region),
"prefix": Property(),
"route_target": Property(),
"linodes": Property(
unordered=True,
),
"is_bgp": Property(),
}
[docs]
@dataclass
class InstanceIPNAT1To1(JSONObject):
"""
InstanceIPNAT1To1 contains information about the NAT 1:1 mapping
of VPC IP together with the VPC and subnet ids.
"""
address: str = ""
subnet_id: int = 0
vpc_id: int = 0
[docs]
@dataclass
class ReservedIPAssignedEntity(JSONObject):
"""
Represents the entity that a reserved IP is assigned to.
NOTE: Reserved IP feature may not currently be available to all users.
"""
id: int = 0
label: str = ""
type: str = ""
url: str = ""
[docs]
class IPAddress(Base):
"""
note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`.
Represents a Linode IP address object.
When attempting to reset the `rdns` field to default, consider using the ExplicitNullValue class::
ip = IPAddress(client, "127.0.0.1")
ip.rdns = ExplicitNullValue
ip.save()
# Re-populate all attributes with new information from the API
ip.invalidate()
API Documentation: https://techdocs.akamai.com/linode-api/reference/get-ip
"""
api_endpoint = "/networking/ips/{address}"
id_attribute = "address"
properties = {
"address": Property(identifier=True),
"gateway": Property(),
"subnet_mask": Property(),
"prefix": Property(),
"type": Property(),
"public": Property(),
"rdns": Property(mutable=True),
"linode_id": Property(),
"interface_id": Property(),
"region": Property(slug_relationship=Region),
"vpc_nat_1_1": Property(json_object=InstanceIPNAT1To1),
"reserved": Property(mutable=True),
"tags": Property(mutable=True, unordered=True),
"assigned_entity": Property(json_object=ReservedIPAssignedEntity),
}
@property
def linode(self):
from .linode import Instance # pylint: disable-all
if not hasattr(self, "_linode"):
self._set("_linode", Instance(self._client, self.linode_id))
return self._linode
@property
def interface(self) -> Optional["LinodeInterface"]:
"""
Returns the Linode Interface associated with this IP address.
NOTE: This function will only return Linode interfaces, not Config interfaces.
:returns: The Linode Interface associated with this IP address.
:rtype: LinodeInterface
"""
from .linode_interfaces import LinodeInterface # pylint: disable-all
if self.interface_id in (None, 0):
self._set("_interface", None)
elif not hasattr(self, "_interface"):
self._set(
"_interface",
LinodeInterface(
self._client, self.linode_id, self.interface_id
),
)
return self._interface
[docs]
def to(self, linode):
"""
This is a helper method for ip-assign, and should not be used outside
of that context. It's used to cleanly build an IP Assign request with
pretty python syntax.
"""
from .linode import Instance # pylint: disable-all
if not isinstance(linode, Instance):
raise ValueError("IP Address can only be assigned to a Linode!")
return {"address": self.address, "linode_id": linode.id}
[docs]
def delete(self):
"""
Override the delete() function from Base to use the correct endpoint.
"""
resp = self._client.delete(
"/linode/instances/{}/ips/{}".format(self.linode_id, self.address),
model=self,
)
if "error" in resp:
return False
self.invalidate()
return True
[docs]
class ReservedIPAddress(Base):
"""
.. note:: This endpoint is in beta. This will only function if base_url is set to ``https://api.linode.com/v4beta``.
Represents a Linode Reserved IPv4 Address.
Update tags on a reserved IP by mutating the ``tags`` attribute and calling ``save()``.
NOTE: Reserved IP feature may not currently be available to all users.
API Documentation: https://techdocs.akamai.com/linode-api/reference/get-reserved-ip
"""
api_endpoint = "/networking/reserved/ips/{address}"
id_attribute = "address"
properties = {
"address": Property(identifier=True),
"gateway": Property(),
"linode_id": Property(),
"prefix": Property(),
"public": Property(),
"rdns": Property(),
"region": Property(slug_relationship=Region),
"reserved": Property(),
"subnet_mask": Property(),
"tags": Property(mutable=True, unordered=True),
"type": Property(),
"assigned_entity": Property(json_object=ReservedIPAssignedEntity),
"interface_id": Property(),
"vpc_nat_1_1": Property(json_object=InstanceIPNAT1To1),
}
[docs]
@dataclass
class VPCIPAddressIPv6(JSONObject):
slaac_address: str = ""
[docs]
@dataclass
class VPCIPAddress(JSONObject):
"""
VPCIPAddress represents the IP address of a VPC.
NOTE: This is not implemented as a typical API object (Base) because VPC IPs
cannot be refreshed through the /networking/ips/{address} endpoint.
"""
address: str = ""
gateway: str = ""
region: str = ""
subnet_mask: str = ""
vpc_id: int = 0
subnet_id: int = 0
linode_id: int = 0
config_id: int = 0
interface_id: int = 0
prefix: int = 0
active: bool = False
address_range: Optional[str] = None
nat_1_1: Optional[str] = None
ipv6_range: Optional[str] = None
ipv6_is_public: Optional[bool] = None
ipv6_addresses: Optional[List[VPCIPAddressIPv6]] = None
[docs]
class VLAN(Base):
"""
.. note:: At this time, the Linode API only supports listing VLANs.
.. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`.
An instance of a Linode VLAN.
VLANs provide a mechanism for secure communication between two or more Linodes that are assigned to the same VLAN.
VLANs are implicitly created during Instance or Instance Config creation.
API Documentation: https://techdocs.akamai.com/linode-api/reference/get-vlans
"""
api_endpoint = "/networking/vlans/{label}"
id_attribute = "label"
properties = {
"label": Property(identifier=True),
"created": Property(is_datetime=True),
"linodes": Property(unordered=True),
"region": Property(slug_relationship=Region),
}
[docs]
@dataclass
class FirewallCreateDevicesOptions(JSONObject):
"""
Represents devices to create created alongside a Linode Firewall.
"""
linodes: List[int] = field(default_factory=list)
nodebalancers: List[int] = field(default_factory=list)
linode_interfaces: List[int] = field(default_factory=list)
[docs]
@dataclass
class FirewallSettingsDefaultFirewallIDs(JSONObject):
"""
Contains the IDs of Linode Firewalls that should be used by default
when creating various interface types.
NOTE: This feature may not currently be available to all users.
"""
include_none_values = True
vpc_interface: Optional[int] = None
public_interface: Optional[int] = None
linode: Optional[int] = None
nodebalancer: Optional[int] = None
[docs]
class FirewallSettings(Base):
"""
Represents the Firewall settings for the current user.
API Documentation: https://techdocs.akamai.com/linode-api/reference/get-firewall-settings
NOTE: This feature may not currently be available to all users.
"""
api_endpoint = "/networking/firewalls/settings"
properties = {
"default_firewall_ids": Property(
json_object=FirewallSettingsDefaultFirewallIDs,
mutable=True,
),
}
[docs]
class FirewallDevice(DerivedBase):
"""
An object representing the assignment between a Linode Firewall and another Linode resource.
API Documentation: https://techdocs.akamai.com/linode-api/reference/get-firewall-device
"""
api_endpoint = "/networking/firewalls/{firewall_id}/devices/{id}"
derived_url_path = "devices"
parent_id_name = "firewall_id"
properties = {
"created": Property(is_datetime=True),
"updated": Property(is_datetime=True),
"entity": Property(),
"id": Property(identifier=True),
}
[docs]
class Firewall(Base):
"""
.. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`.
An instance of a Linode Cloud Firewall.
API Documentation: https://techdocs.akamai.com/linode-api/reference/get-firewall
"""
api_endpoint = "/networking/firewalls/{id}"
properties = {
"id": Property(identifier=True),
"label": Property(mutable=True),
"tags": Property(mutable=True, unordered=True),
"status": Property(mutable=True),
"created": Property(is_datetime=True),
"updated": Property(is_datetime=True),
"devices": Property(derived_class=FirewallDevice),
"rules": Property(),
}
[docs]
def update_rules(self, rules):
"""
Sets the JSON rules for this Firewall.
API Documentation: https://techdocs.akamai.com/linode-api/reference/put-firewall-rules
:param rules: The rules to apply to this Firewall.
:type rules: dict
"""
self._client.put(
"{}/rules".format(self.api_endpoint), model=self, data=rules
)
self.invalidate()
[docs]
def get_rules(self):
"""
Gets the JSON rules for this Firewall.
API Documentation: https://techdocs.akamai.com/linode-api/reference/put-firewall-rules
:returns: The rules that this Firewall is currently configured with.
:rtype: dict
"""
return self._client.get(
"{}/rules".format(self.api_endpoint), model=self
)
@property
def rule_versions(self):
"""
Gets the JSON rule versions for this Firewall.
API Documentation: https://techdocs.akamai.com/linode-api/reference/get-firewall-rule-versions
:returns: Lists the current and historical rules of the firewall (that is not deleted),
using version. Whenever the rules update, the version increments from 1.
:rtype: dict
"""
return self._client.get(
"{}/history".format(self.api_endpoint), model=self
)
[docs]
def get_rule_version(self, version):
"""
Gets the JSON for a specific rule version for this Firewall.
API Documentation: https://techdocs.akamai.com/linode-api/reference/get-firewall-rule-version
:param version: The firewall rule version to view.
:type version: int
:returns: Gets a specific firewall rule version for an enabled or disabled firewall.
:rtype: dict
"""
return self._client.get(
"{}/history/rules/{}".format(self.api_endpoint, version), model=self
)
[docs]
def device_create(self, id, type="linode", **kwargs):
"""
Creates and attaches a device to this Firewall
API Documentation: https://techdocs.akamai.com/linode-api/reference/post-firewall-device
:param id: The ID of the entity to create a device for.
:type id: int
:param type: The type of entity the device is being created for. (`linode`)
:type type: str
"""
params = {
"id": id,
"type": type,
}
params.update(kwargs)
result = self._client.post(
"{}/devices".format(Firewall.api_endpoint), model=self, data=params
)
self.invalidate()
if not "id" in result:
raise UnexpectedResponseError(
"Unexpected response creating device!", json=result
)
c = FirewallDevice(self._client, result["id"], self.id, result)
return c
[docs]
class FirewallTemplate(Base):
"""
Represents a single Linode Firewall template.
API documentation: https://techdocs.akamai.com/linode-api/reference/get-firewall-template
NOTE: This feature may not currently be available to all users.
"""
api_endpoint = "/networking/firewalls/templates/{slug}"
id_attribute = "slug"
properties = {"slug": Property(identifier=True), "rules": Property()}
[docs]
class NetworkTransferPrice(Base):
"""
An NetworkTransferPrice represents the structure of a valid network transfer price.
Currently the NetworkTransferPrice can only be retrieved by listing, i.e.:
types = client.networking.transfer_prices()
API documentation: https://techdocs.akamai.com/linode-api/reference/get-network-transfer-prices
"""
properties = {
"id": Property(identifier=True),
"label": Property(),
"price": Property(json_object=Price),
"region_prices": Property(json_object=RegionPrice),
"transfer": Property(),
}
[docs]
class ReservedIPType(Base):
"""
Represents a reserved IP type with pricing information.
NOTE: Reserved IP feature may not currently be available to all users.
API Documentation: https://techdocs.akamai.com/linode-api/reference/get-reserved-ip-types
"""
properties = {
"id": Property(identifier=True),
"label": Property(),
"price": Property(json_object=Price),
"region_prices": Property(json_object=RegionPrice),
}