linode / linode_api4-python

Official Python bindings for the Linode API
https://linode-api4.readthedocs.io/en/latest/
BSD 3-Clause "New" or "Revised" License
135 stars 75 forks source link

new: Add support for LKE node pool labels & taints #448

Closed lgarber-akamai closed 1 month ago

lgarber-akamai commented 1 month ago

šŸ“ Description

This pull request adds support for specifying the labels and taints field when creating, updating and accessing an LKE node pool.

Additionally, this pull request makes the following improvements to the object serialization logic:

āœ”ļø How to Test

The following test steps assume you have pulled down this PR locally and run make install.

Unit Testing

make testunit

Integration Testing

make TEST_COMMAND=models/lke

Manual Testing

  1. In a linode_api4-python sandbox environment (e.g. dx-devenv), run the following:
import json
import os

from linode_api4 import LinodeClient, LKENodePoolTaint

client = LinodeClient(os.getenv("LINODE_TOKEN"))

# Create a cluster with labels and taints
cluster = client.lke.cluster_create(
    region="us-mia",
    label="test-cluster",
    kube_version="1.30",
    node_pools=[
        client.lke.node_pool(
            "g6-standard-1",
            2,
            labels={
                "foo.example.com/test": "bar",
                "foo.example.com/test2": "test",
            },
            taints=[
                LKENodePoolTaint(
                    key="foo.example.com/test", value="bar", effect="NoSchedule"
                )
            ],
        )
    ],
)

target_pool = cluster.pools[0]

print(f"Initial node pool:\n{json.dumps(target_pool._serialize(), indent=4)}\n")

# Update the labels and taints on this cluster
updated_labels = {
    "foo.example.com/test": "bar",
    "foo.example.com/test3": "cool",
}

updated_taints = [
    LKENodePoolTaint(key="foo.example.com/test3", value="cool", effect="NoExecute")
]

target_pool.labels = updated_labels
target_pool.taints = updated_taints

print(f"Updated pool (pre-refresh):\n{json.dumps(target_pool._serialize(), indent=4)}\n")

# Invalid the pool so it is implicitly refreshed
target_pool.invalidate()

print(f"Updated pool (post-refresh):\n{json.dumps(target_pool._serialize(), indent=4)}\n")
  1. Ensure the output matches the following:
Initial node pool:
{
    "count": 2,
    "autoscaler": {
        "enabled": false,
        "min": 2,
        "max": 2
    },
    "tags": [],
    "labels": {
        "foo.example.com/test": "bar",
        "foo.example.com/test2": "test"
    },
    "taints": [
        {
            "key": "foo.example.com/test",
            "value": "bar",
            "effect": "NoSchedule"
        }
    ]
}

Updated pool (pre-refresh):
{
    "count": 2,
    "autoscaler": {
        "enabled": false,
        "min": 2,
        "max": 2
    },
    "tags": [],
    "labels": {
        "foo.example.com/test": "bar",
        "foo.example.com/test3": "cool"
    },
    "taints": [
        {
            "key": "foo.example.com/test3",
            "value": "cool",
            "effect": "NoExecute"
        }
    ]
}

Updated pool (post-refresh):
{
    "count": 2,
    "autoscaler": {
        "enabled": false,
        "min": 2,
        "max": 2
    },
    "tags": [],
    "labels": {
        "foo.example.com/test": "bar",
        "foo.example.com/test2": "test"
    },
    "taints": [
        {
            "key": "foo.example.com/test",
            "value": "bar",
            "effect": "NoSchedule"
        }
    ]
}