happymatei
happymatei

Reputation: 213

Update/Add labels to Google Kubernetes Engine Cluster Workloads through Python API

Has anyone tried to add or update the Clusters from Google Kubernetes Engine through Python API?

I managed to do this for Compute instances, but the guide for Kubernetes Engine says its deprecated:

https://cloud.google.com/kubernetes-engine/docs/reference/rest/v1/projects.zones.clusters.nodePools/update

Tried it and it fails saying it does not find "labels":

googleapiclient.errors.HttpError: <HttpError 400 when requesting https://container.googleapis.com/v1/projects/testingproject/zones/us-east1/clusters/testing-cluster/resourceLabels?alt=json returned "Invalid JSON payload received. Unknown name "labels": Cannot find field.". Details: "[{'@type': 'type.googleapis.com/google.rpc.BadRequest', 'fieldViolations': [{'description': 'Invalid JSON payload received. Unknown name "labels": Cannot find field.'}]}]">

My code is this:

credentials = GoogleCredentials.get_application_default()

service = discovery.build('container', 'v1', credentials=credentials)

# Deprecated. The Google Developers Console [project ID or project
# number](https://developers.google.com/console/help/new/#projectnumber).
# This field has been deprecated and replaced by the name field.
project_id = 'testingproject'  # TODO: Update placeholder value.

# Deprecated. The name of the Google Compute Engine
# [zone](/compute/docs/zones#available) in which the cluster
# resides.
# This field has been deprecated and replaced by the name field.
zone = 'us-east1'  # TODO: Update placeholder value.

# Deprecated. The name of the cluster.
# This field has been deprecated and replaced by the name field.
cluster_id = 'testing-cluster'  # TODO: Update placeholder value.

set_labels_request_body = {
    'labels': 'value'
}

request = service.projects().zones().clusters().resourceLabels(projectId=project_id, zone=zone, clusterId=cluster_id, body=set_labels_request_body)
response = request.execute()

# TODO: Change code below to process the `response` dict:
pprint(response)

I want to update the Workload named 'matei-testing-2000-gke-ops' inside the cluster 'testing-cluster'.

Any ideas? Thank you

Update: It does not find the labels because the name is resourceLabels. But I get the following error after:

googleapiclient.errors.HttpError: <HttpError 400 when requesting https://container.googleapis.com/v1/projects//zones//clusters//resourceLabels?alt=json returned "Invalid value at 'resource_labels' (type.googleapis.com/google.container.v1.SetLabelsRequest.ResourceLabelsEntry), "value"". Details: "[{'@type': 'type.googleapis.com/google.rpc.BadRequest', 'fieldViolations': [{'field': 'resource_labels', 'description': 'Invalid value at 'resource_labels' (type.googleapis.com/google.container.v1.SetLabelsRequest.ResourceLabelsEntry), "value"'}]}]">

Upvotes: 0

Views: 588

Answers (1)

DazWilkin
DazWilkin

Reputation: 40091

I've not now tried this.

But IIUC, you'll need to:

  • ditch (or use defaults) for e.g. project_id, zone and cluster_id parameters of resourceLabels
  • add name to your body and it should be of the form: projects/*/locations/*/clusters/*

i.e.

import os
from googleapiclient import discovery
from oauth2client.client import GoogleCredentials

credentials = GoogleCredentials.get_application_default()

service = discovery.build('container', 'v1', credentials=credentials)

PROJECT = os.getenv("PROJECT")
LOCATION = os.getenv("ZONE")
CLUSTER = os.getenv("CLUSTER")

NAME = "projects/{project}/locations/{location}/clusters/{cluster}".format(
        project=project_id,
        location=zone,
        cluster=cluster_id)


# To update `resourceLabels` you must first fingerprint them
# To get the current `labelFingerprint`, you must `get` the cluster

body = {
    'name': NAME,
}

request = service.projects().zones().clusters().get(
    projectId=project_id,
    zone=zone,
    clusterId=cluster_id)
response = request.execute()

labelFingerprint = response["labelFingerprint"]

if "resourceLabels" in response:
    print("Existing labels")
    resourceLabels = response["resourceLabels"]
else:
    print("No labels")
    resourceLabels = {}

# Add|update a label
resourceLabels["dog"] = "freddie"

# Construct `resourceLabels` request
body = {
    'name': NAME,
    'resourceLabels': resourceLabels,
     'labelFingerprint': labelFingerprint,
}

request = service.projects().zones().clusters().resourceLabels(
    projectId=project_id,
    zone=zone,
    clusterId=cluster_id,
    body=body)

# Do something with the `response`
response = request.execute()

And

gcloud container clusters describe ${CLUSTER} \
--zone=${ZONE} \
--project=${PROJECT} \
--format="value(labelFingerprint,resourceLabels)"

Before:

a9dc16a7    

After:

b2c32ec0    dog=freddie

Upvotes: 1

Related Questions