自定义 Kubernetes GO 运算符的通用 client.Get

Generic client.Get for custom Kubernetes GO operator

在使用 golang 中的 operator-sdk 实现的自定义 Kubernetes 运算符中,是否可以直接调用自定义 API 并将对象检索为 YAML?

例如。我有一个自定义资源

apiVersion: test.com/v1alpha1
kind: TEST
metadata::
  name: example-test
spec:
  replicas: 3
  randomname: value

我事先不知道规范中的哪些字段与副本不同。所以我无法创建包含用于保存条目的结构的 go 类型。

所以与其这样做:

instance := &testv1alpha1.Test{}
err := r.client.Get(context.TODO(), nameSpaceName, instance)

我希望能够做类似的事情:

instanceYAML := genericContainer{}
err := r.client.GetGeneric(context.TODO(), nameSpaceName, instance)

然后解析 instanceYAML 以检查条目。

这称为 "unstructured" 客户端。文档非常简单,所以我建议查看测试示例 https://github.com/kubernetes-sigs/controller-runtime/blob/ea32729106c995d9df310ac4731c2061490addfb/pkg/client/client_test.go#L1536-L1566

使用 unstructured type client 所有在 CoreAPI 资源上完成的操作都可以在 CustomResourceDefinition(CRD)

上完成
package util

import (
    "context"
    "encoding/json"
    "strconv"

    "github.com/go-logr/logr"
    "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    "k8s.io/apimachinery/pkg/runtime/schema"
    types "k8s.io/apimachinery/pkg/types"
    _ "k8s.io/client-go/plugin/pkg/client/auth"
    "sigs.k8s.io/controller-runtime/pkg/client"
)

var reqLogger logr.Logger

func CRUDonCRD(c client.Client) {
    u := createUnstructuredObject(c)
    GetCR(u, c)
    PatchCR(u, c, 1)
    DeleteCR(u, c)
}

func createUnstructuredObject(c client.Client) *unstructured.Unstructured {
    u := &unstructured.Unstructured{}

    u.SetGroupVersionKind(schema.GroupVersionKind{
        // Group:   "<crd group name>",
        // Kind:    "<crd kind>",
        // Version: "<crd version>",
        Group:   "com.cumulus.netq.operator.transport",
        Kind:    "TransportOperator",
        Version: "v1",
    })

    _ = c.Get(context.Background(), client.ObjectKey{
        // Namespace: "<namespace>",
        // Name:      "cr name",
        Namespace: "default",
        Name:      "transport-operator",
    }, u)

    return u
}

type patchStringValue struct {
    Op    string `json:"op"`
    Path  string `json:"path"`
    Value string `json:"value"`
}

func PatchCR(u *unstructured.Unstructured, c client.Client, replicaCount int) error {

    payload := []patchStringValue{{
        Op:    "replace",
        Path:  "/spec/replicas/replicasOpta",
        Value: strconv.Itoa(replicaCount),
    }}
    payloadBytes, _ := json.Marshal(payload)

    err := c.Patch(context.Background(), u, client.RawPatch(types.JSONPatchType, payloadBytes))
    if err != nil {
        reqLogger.Error(err, "error occured while patching")
    }

    reqLogger.Info("Patching is successful", "Patched Transport Operator Object", u)
    return err
}

func GetCR(u *unstructured.Unstructured, c client.Client) {

    // key := client.ObjectKey{Namespace: "default", Name: "<cr-name>"}
    key := client.ObjectKey{Namespace: "default", Name: "transport-operator"}
    err := c.Get(context.Background(), key, u)
    if err != nil {
        reqLogger.Error(err, "error occured while getting the resource")
    }

    reqLogger.Info("Got the resource", "Resource Object", u)
}

func DeleteCR(u *unstructured.Unstructured, c client.Client) {
    err := c.Delete(context.Background(), u)
    if err != nil {
        reqLogger.Error(err, "error occured while deleting the resource")
    }

    reqLogger.Info("Resource deleted", "Resource ", u)
}