Skip to content

Commit

Permalink
new: Support pricing for LKE, Volume, NodeBalancer and Network Transf…
Browse files Browse the repository at this point in the history
…er (#454)

* support pricing

* Add more detailed assertions for integration tests

---------

Co-authored-by: ykim-1 <ykim@akamai.com>
  • Loading branch information
yec-akamai and ykim-1 committed Sep 11, 2024
1 parent cace635 commit 1d155a9
Show file tree
Hide file tree
Showing 19 changed files with 460 additions and 6 deletions.
24 changes: 24 additions & 0 deletions linode_api4/common.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import os
from dataclasses import dataclass

from linode_api4.objects import JSONObject

SSH_KEY_TYPES = (
"ssh-dss",
Expand Down Expand Up @@ -57,3 +60,24 @@ def load_and_validate_keys(authorized_keys):
)
)
return ret


@dataclass
class Price(JSONObject):
"""
Price contains the core fields of a price object returned by various pricing endpoints.
"""

hourly: int = 0
monthly: int = 0


@dataclass
class RegionPrice(JSONObject):
"""
RegionPrice contains the core fields of a region_price object returned by various pricing endpoints.
"""

id: int = 0
hourly: int = 0
monthly: int = 0
19 changes: 19 additions & 0 deletions linode_api4/groups/lke.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
KubeVersion,
LKECluster,
LKEClusterControlPlaneOptions,
LKEType,
Type,
drop_null_keys,
)
Expand Down Expand Up @@ -155,3 +156,21 @@ def node_pool(self, node_type: Union[Type, str], node_count: int, **kwargs):
result.update(kwargs)

return result

def types(self, *filters):
"""
Returns a :any:`PaginatedList` of :any:`LKEType` objects that represents a valid LKE type.
API Documentation: TODO
:param filters: Any number of filters to apply to this query.
See :doc:`Filtering Collections</linode_api4/objects/filtering>`
for more details on filtering.
:returns: A Paginated List of LKE types that match the query.
:rtype: PaginatedList of LKEType
"""

return self.client._get_and_filter(
LKEType, *filters, endpoint="/lke/types"
)
19 changes: 19 additions & 0 deletions linode_api4/groups/networking.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
IPAddress,
IPv6Pool,
IPv6Range,
NetworkTransferPrice,
Region,
)

Expand Down Expand Up @@ -348,3 +349,21 @@ def ip_addresses_assign(self, assignments, region):
params = {"assignments": assignments, "region": region}

self.client.post("/networking/ips/assign", model=self, data=params)

def transfer_prices(self, *filters):
"""
Returns a :any:`PaginatedList` of :any:`NetworkTransferPrice` objects that represents a valid network transfer price.
API Documentation: TODO
:param filters: Any number of filters to apply to this query.
See :doc:`Filtering Collections</linode_api4/objects/filtering>`
for more details on filtering.
:returns: A Paginated List of network transfer price that match the query.
:rtype: PaginatedList of NetworkTransferPrice
"""

return self.client._get_and_filter(
NetworkTransferPrice, *filters, endpoint="/network-transfer/prices"
)
20 changes: 19 additions & 1 deletion linode_api4/groups/nodebalancer.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from linode_api4.errors import UnexpectedResponseError
from linode_api4.groups import Group
from linode_api4.objects import Base, NodeBalancer
from linode_api4.objects import Base, NodeBalancer, NodeBalancerType


class NodeBalancerGroup(Group):
Expand Down Expand Up @@ -50,3 +50,21 @@ def create(self, region, **kwargs):

n = NodeBalancer(self.client, result["id"], result)
return n

def types(self, *filters):
"""
Returns a :any:`PaginatedList` of :any:`NodeBalancerType` objects that represents a valid NodeBalancer type.
API Documentation: TODO
:param filters: Any number of filters to apply to this query.
See :doc:`Filtering Collections</linode_api4/objects/filtering>`
for more details on filtering.
:returns: A Paginated List of NodeBalancer types that match the query.
:rtype: PaginatedList of NodeBalancerType
"""

return self.client._get_and_filter(
NodeBalancerType, *filters, endpoint="/nodebalancers/types"
)
20 changes: 19 additions & 1 deletion linode_api4/groups/volume.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from linode_api4.errors import UnexpectedResponseError
from linode_api4.groups import Group
from linode_api4.objects import Base, Volume
from linode_api4.objects import Base, Volume, VolumeType


class VolumeGroup(Group):
Expand Down Expand Up @@ -71,3 +71,21 @@ def create(self, label, region=None, linode=None, size=20, **kwargs):

v = Volume(self.client, result["id"], result)
return v

def types(self, *filters):
"""
Returns a :any:`PaginatedList` of :any:`VolumeType` objects that represents a valid Volume type.
API Documentation: TODO
:param filters: Any number of filters to apply to this query.
See :doc:`Filtering Collections</linode_api4/objects/filtering>`
for more details on filtering.
:returns: A Paginated List of Volume types that match the query.
:rtype: PaginatedList of VolumeType
"""

return self.client._get_and_filter(
VolumeType, *filters, endpoint="/volumes/types"
)
2 changes: 1 addition & 1 deletion linode_api4/objects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from .region import Region
from .image import Image
from .linode import *
from .volume import Volume
from .volume import *
from .domain import *
from .account import *
from .networking import *
Expand Down
19 changes: 19 additions & 0 deletions linode_api4/objects/lke.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from typing import Any, Dict, List, Optional, Union
from urllib import parse

from linode_api4.common import Price, RegionPrice
from linode_api4.errors import UnexpectedResponseError
from linode_api4.objects import (
Base,
Expand All @@ -15,6 +16,24 @@
)


class LKEType(Base):
"""
An LKEType represents the structure of a valid LKE type.
Currently the LKEType can only be retrieved by listing, i.e.:
types = client.lke.types()
API documentation: TODO
"""

properties = {
"id": Property(identifier=True),
"label": Property(),
"price": Property(json_object=Price),
"region_prices": Property(json_object=RegionPrice),
"transfer": Property(),
}


class KubeVersion(Base):
"""
A KubeVersion is a version of Kubernetes that can be deployed on LKE.
Expand Down
19 changes: 19 additions & 0 deletions linode_api4/objects/networking.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from dataclasses import dataclass
from typing import Optional

from linode_api4.common import Price, RegionPrice
from linode_api4.errors import UnexpectedResponseError
from linode_api4.objects import Base, DerivedBase, JSONObject, Property, Region

Expand Down Expand Up @@ -256,3 +257,21 @@ def device_create(self, id, type="linode", **kwargs):

c = FirewallDevice(self._client, result["id"], self.id, result)
return c


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: TODO
"""

properties = {
"id": Property(identifier=True),
"label": Property(),
"price": Property(json_object=Price),
"region_prices": Property(json_object=RegionPrice),
"transfer": Property(),
}
19 changes: 19 additions & 0 deletions linode_api4/objects/nodebalancer.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
from urllib import parse

from linode_api4.common import Price, RegionPrice
from linode_api4.errors import UnexpectedResponseError
from linode_api4.objects import (
Base,
Expand All @@ -12,6 +13,24 @@
from linode_api4.objects.networking import Firewall, IPAddress


class NodeBalancerType(Base):
"""
An NodeBalancerType represents the structure of a valid NodeBalancer type.
Currently the NodeBalancerType can only be retrieved by listing, i.e.:
types = client.nodebalancers.types()
API documentation: TODO
"""

properties = {
"id": Property(identifier=True),
"label": Property(),
"price": Property(json_object=Price),
"region_prices": Property(json_object=RegionPrice),
"transfer": Property(),
}


class NodeBalancerNode(DerivedBase):
"""
The information about a single Node, a backend for this NodeBalancer’s configured port.
Expand Down
19 changes: 19 additions & 0 deletions linode_api4/objects/volume.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
from linode_api4.common import Price, RegionPrice
from linode_api4.errors import UnexpectedResponseError
from linode_api4.objects import Base, Instance, Property, Region


class VolumeType(Base):
"""
An VolumeType represents the structure of a valid Volume type.
Currently the VolumeType can only be retrieved by listing, i.e.:
types = client.volumes.types()
API documentation: TODO
"""

properties = {
"id": Property(identifier=True),
"label": Property(),
"price": Property(json_object=Price),
"region_prices": Property(json_object=RegionPrice),
"transfer": Property(),
}


class Volume(Base):
"""
A single Block Storage Volume. Block Storage Volumes are persistent storage devices
Expand Down
38 changes: 38 additions & 0 deletions test/fixtures/lke_types.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"data": [
{
"id": "lke-sa",
"label": "LKE Standard Availability",
"price": {
"hourly": 0,
"monthly": 0
},
"region_prices": [],
"transfer": 0
},
{
"id": "lke-ha",
"label": "LKE High Availability",
"price": {
"hourly": 0.09,
"monthly": 60
},
"region_prices": [
{
"id": "id-cgk",
"hourly": 0.108,
"monthly": 72
},
{
"id": "br-gru",
"hourly": 0.126,
"monthly": 84
}
],
"transfer": 0
}
],
"page": 1,
"pages": 1,
"results": 2
}
38 changes: 38 additions & 0 deletions test/fixtures/network-transfer_prices.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"data": [
{
"id": "distributed_network_transfer",
"label": "Distributed Network Transfer",
"price": {
"hourly": 0.01,
"monthly": null
},
"region_prices": [],
"transfer": 0
},
{
"id": "network_transfer",
"label": "Network Transfer",
"price": {
"hourly": 0.005,
"monthly": null
},
"region_prices": [
{
"id": "id-cgk",
"hourly": 0.015,
"monthly": null
},
{
"id": "br-gru",
"hourly": 0.007,
"monthly": null
}
],
"transfer": 0
}
],
"page": 1,
"pages": 1,
"results": 2
}
28 changes: 28 additions & 0 deletions test/fixtures/nodebalancers_types.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"data": [
{
"id": "nodebalancer",
"label": "NodeBalancer",
"price": {
"hourly": 0.015,
"monthly": 10
},
"region_prices": [
{
"id": "id-cgk",
"hourly": 0.018,
"monthly": 12
},
{
"id": "br-gru",
"hourly": 0.021,
"monthly": 14
}
],
"transfer": 0
}
],
"page": 1,
"pages": 1,
"results": 1
}
Loading

0 comments on commit 1d155a9

Please sign in to comment.