Skip to content

Commit 95970e4

Browse files
Implement Support for LKE Enterprise (#521)
* Implement support for LKE enterprise * Correct test
1 parent 3692712 commit 95970e4

File tree

12 files changed

+297
-8
lines changed

12 files changed

+297
-8
lines changed

linode_api4/groups/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from .image import *
99
from .linode import *
1010
from .lke import *
11+
from .lke_tier import *
1112
from .longview import *
1213
from .networking import *
1314
from .nodebalancer import *

linode_api4/groups/lke.py

+24-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
from typing import Any, Dict, Union
1+
from typing import Any, Dict, Optional, Union
22

33
from linode_api4.errors import UnexpectedResponseError
44
from linode_api4.groups import Group
5+
from linode_api4.groups.lke_tier import LKETierGroup
56
from linode_api4.objects import (
67
KubeVersion,
78
LKECluster,
@@ -67,6 +68,7 @@ def cluster_create(
6768
LKEClusterControlPlaneOptions, Dict[str, Any]
6869
] = None,
6970
apl_enabled: bool = False,
71+
tier: Optional[str] = None,
7072
**kwargs,
7173
):
7274
"""
@@ -104,9 +106,13 @@ def cluster_create(
104106
:param control_plane: The control plane configuration of this LKE cluster.
105107
:type control_plane: Dict[str, Any] or LKEClusterControlPlaneRequest
106108
:param apl_enabled: Whether this cluster should use APL.
107-
NOTE: This endpoint is in beta and may only
109+
NOTE: This field is in beta and may only
108110
function if base_url is set to `https://api.linode.com/v4beta`.
109111
:type apl_enabled: bool
112+
:param tier: The tier of LKE cluster to create.
113+
NOTE: This field is in beta and may only
114+
function if base_url is set to `https://api.linode.com/v4beta`.
115+
:type tier: str
110116
:param kwargs: Any other arguments to pass along to the API. See the API
111117
docs for possible values.
112118
@@ -122,6 +128,7 @@ def cluster_create(
122128
node_pools if isinstance(node_pools, list) else [node_pools]
123129
),
124130
"control_plane": control_plane,
131+
"tier": tier,
125132
}
126133
params.update(kwargs)
127134

@@ -183,3 +190,18 @@ def types(self, *filters):
183190
return self.client._get_and_filter(
184191
LKEType, *filters, endpoint="/lke/types"
185192
)
193+
194+
def tier(self, id: str) -> LKETierGroup:
195+
"""
196+
Returns an object representing the LKE tier API path.
197+
198+
NOTE: LKE tiers may not currently be available to all users.
199+
200+
:param id: The ID of the tier.
201+
:type id: str
202+
203+
:returns: An object representing the LKE tier API path.
204+
:rtype: LKETier
205+
"""
206+
207+
return LKETierGroup(self.client, id)

linode_api4/groups/lke_tier.py

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from linode_api4.groups import Group
2+
from linode_api4.objects import TieredKubeVersion
3+
4+
5+
class LKETierGroup(Group):
6+
"""
7+
Encapsulates methods related to a specific LKE tier. This
8+
should not be instantiated on its own, but should instead be used through
9+
an instance of :any:`LinodeClient`::
10+
11+
client = LinodeClient(token)
12+
instances = client.lke.tier("standard") # use the LKETierGroup
13+
14+
This group contains all features beneath the `/lke/tiers/{tier}` group in the API v4.
15+
"""
16+
17+
def __init__(self, client: "LinodeClient", tier: str):
18+
super().__init__(client)
19+
self.tier = tier
20+
21+
def versions(self, *filters):
22+
"""
23+
Returns a paginated list of versions for this tier matching the given filters.
24+
25+
API Documentation: Not Yet Available
26+
27+
:param filters: Any number of filters to apply to this query.
28+
See :doc:`Filtering Collections</linode_api4/objects/filtering>`
29+
for more details on filtering.
30+
31+
:returns: A paginated list of kube versions that match the query.
32+
:rtype: PaginatedList of TieredKubeVersion
33+
"""
34+
35+
return self.client._get_and_filter(
36+
TieredKubeVersion,
37+
endpoint=f"/lke/tiers/{self.tier}/versions",
38+
parent_id=self.tier,
39+
*filters,
40+
)

linode_api4/linode_client.py

+14-3
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,13 @@ def volume_create(self, label, region=None, linode=None, size=20, **kwargs):
455455
)
456456

457457
# helper functions
458-
def _get_and_filter(self, obj_type, *filters, endpoint=None):
458+
def _get_and_filter(
459+
self,
460+
obj_type,
461+
*filters,
462+
endpoint=None,
463+
parent_id=None,
464+
):
459465
parsed_filters = None
460466
if filters:
461467
if len(filters) > 1:
@@ -467,8 +473,13 @@ def _get_and_filter(self, obj_type, *filters, endpoint=None):
467473

468474
# Use sepcified endpoint
469475
if endpoint:
470-
return self._get_objects(endpoint, obj_type, filters=parsed_filters)
476+
return self._get_objects(
477+
endpoint, obj_type, parent_id=parent_id, filters=parsed_filters
478+
)
471479
else:
472480
return self._get_objects(
473-
obj_type.api_list(), obj_type, filters=parsed_filters
481+
obj_type.api_list(),
482+
obj_type,
483+
parent_id=parent_id,
484+
filters=parsed_filters,
474485
)

linode_api4/objects/lke.py

+48-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
Region,
1515
Type,
1616
)
17+
from linode_api4.objects.base import _flatten_request_body_recursive
1718
from linode_api4.util import drop_null_keys
1819

1920

@@ -49,6 +50,26 @@ class KubeVersion(Base):
4950
}
5051

5152

53+
class TieredKubeVersion(DerivedBase):
54+
"""
55+
A TieredKubeVersion is a version of Kubernetes that is specific to a certain LKE tier.
56+
57+
NOTE: LKE tiers may not currently be available to all users.
58+
59+
API Documentation: https://techdocs.akamai.com/linode-api/reference/get-lke-version
60+
"""
61+
62+
api_endpoint = "/lke/tiers/{tier}/versions/{id}"
63+
parent_id_name = "tier"
64+
id_attribute = "id"
65+
derived_url_path = "versions"
66+
67+
properties = {
68+
"id": Property(identifier=True),
69+
"tier": Property(identifier=True),
70+
}
71+
72+
5273
@dataclass
5374
class LKENodePoolTaint(JSONObject):
5475
"""
@@ -154,6 +175,8 @@ class LKENodePool(DerivedBase):
154175
An LKE Node Pool describes a pool of Linode Instances that exist within an
155176
LKE Cluster.
156177
178+
NOTE: The k8s_version and update_strategy fields are only available for LKE Enterprise clusters.
179+
157180
API Documentation: https://techdocs.akamai.com/linode-api/reference/get-lke-node-pool
158181
"""
159182

@@ -175,6 +198,12 @@ class LKENodePool(DerivedBase):
175198
"tags": Property(mutable=True, unordered=True),
176199
"labels": Property(mutable=True),
177200
"taints": Property(mutable=True),
201+
# Enterprise-specific properties
202+
# Ideally we would use slug_relationship=TieredKubeVersion here, but
203+
# it isn't possible without an extra request because the tier is not
204+
# directly exposed in the node pool response.
205+
"k8s_version": Property(mutable=True),
206+
"update_strategy": Property(mutable=True),
178207
}
179208

180209
def _parse_raw_node(
@@ -255,6 +284,7 @@ class LKECluster(Base):
255284
"pools": Property(derived_class=LKENodePool),
256285
"control_plane": Property(mutable=True),
257286
"apl_enabled": Property(),
287+
"tier": Property(),
258288
}
259289

260290
def invalidate(self):
@@ -385,6 +415,10 @@ def node_pool_create(
385415
node_count: int,
386416
labels: Optional[Dict[str, str]] = None,
387417
taints: List[Union[LKENodePoolTaint, Dict[str, Any]]] = None,
418+
k8s_version: Optional[
419+
Union[str, KubeVersion, TieredKubeVersion]
420+
] = None,
421+
update_strategy: Optional[str] = None,
388422
**kwargs,
389423
):
390424
"""
@@ -399,7 +433,13 @@ def node_pool_create(
399433
:param labels: A dict mapping labels to their values to apply to this pool.
400434
:type labels: Dict[str, str]
401435
:param taints: A list of taints to apply to this pool.
402-
:type taints: List of :any:`LKENodePoolTaint` or dict
436+
:type taints: List of :any:`LKENodePoolTaint` or dict.
437+
:param k8s_version: The Kubernetes version to use for this pool.
438+
NOTE: This field is specific to enterprise clusters.
439+
:type k8s_version: str, KubeVersion, or TieredKubeVersion
440+
:param update_strategy: The strategy to use when updating this node pool.
441+
NOTE: This field is specific to enterprise clusters.
442+
:type update_strategy: str
403443
:param kwargs: Any other arguments to pass to the API. See the API docs
404444
for possible values.
405445
@@ -409,6 +449,10 @@ def node_pool_create(
409449
params = {
410450
"type": node_type,
411451
"count": node_count,
452+
"labels": labels,
453+
"taints": taints,
454+
"k8s_version": k8s_version,
455+
"update_strategy": update_strategy,
412456
}
413457

414458
if labels is not None:
@@ -420,7 +464,9 @@ def node_pool_create(
420464
params.update(kwargs)
421465

422466
result = self._client.post(
423-
"{}/pools".format(LKECluster.api_endpoint), model=self, data=params
467+
"{}/pools".format(LKECluster.api_endpoint),
468+
model=self,
469+
data=drop_null_keys(_flatten_request_body_recursive(params)),
424470
)
425471
self.invalidate()
426472

test/fixtures/lke_clusters_18881.json

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"label": "example-cluster",
77
"region": "ap-west",
88
"k8s_version": "1.19",
9+
"tier": "standard",
910
"tags": [],
1011
"control_plane": {
1112
"high_availability": true

test/fixtures/lke_clusters_18882.json

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"id": 18881,
3+
"status": "ready",
4+
"created": "2021-02-10T23:54:21",
5+
"updated": "2021-02-10T23:54:21",
6+
"label": "example-cluster-2",
7+
"region": "ap-west",
8+
"k8s_version": "1.31.1+lke1",
9+
"tier": "enterprise",
10+
"tags": [],
11+
"control_plane": {
12+
"high_availability": true
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"id": 789,
3+
"type": "g6-standard-2",
4+
"count": 3,
5+
"nodes": [],
6+
"disks": [],
7+
"autoscaler": {
8+
"enabled": false,
9+
"min": 3,
10+
"max": 3
11+
},
12+
"labels": {},
13+
"taints": [],
14+
"tags": [],
15+
"disk_encryption": "enabled",
16+
"k8s_version": "1.31.1+lke1",
17+
"update_strategy": "rolling_update"
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"data": [
3+
{
4+
"id": "1.32",
5+
"tier": "standard"
6+
},
7+
{
8+
"id": "1.31",
9+
"tier": "standard"
10+
},
11+
{
12+
"id": "1.30",
13+
"tier": "standard"
14+
}
15+
],
16+
"page": 1,
17+
"pages": 1,
18+
"results": 3
19+
}

0 commit comments

Comments
 (0)