zncdatadev / trino-operator

Operator for Trino, the distributed SQL query engine for big data
Apache License 2.0
3 stars 6 forks source link

[Feature]: CRD too long, to reduce crd size #155

Open whg517 opened 2 months ago

whg517 commented 2 months ago

trace

Implement with memcached example

define go struct with kubebuilder


package v1alpha1

import (
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/apimachinery/pkg/runtime"
)

// MemcachedSpec defines the desired state of Memcached
type MemcachedSpec struct {
    // +kubebuilder:pruning:PreserveUnknownFields
    // +kubebuilder:validation:Type=object
    // +kubebuilder:validation:Optional
    Afficinity *runtime.RawExtension `json:"affinity,omitempty"`

    // +kubebuilder:pruning:PreserveUnknownFields
    // +kubebuilder:validation:Type=object
    // +kubebuilder:validation:Optional
    PodOverrides *runtime.RawExtension `json:"podOverrides,omitempty"`
}

// MemcachedStatus defines the observed state of Memcached
type MemcachedStatus struct {
}

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status

// Memcached is the Schema for the memcacheds API
type Memcached struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    Spec   MemcachedSpec   `json:"spec,omitempty"`
    Status MemcachedStatus `json:"status,omitempty"`
}

//+kubebuilder:object:root=true

// MemcachedList contains a list of Memcached
type MemcachedList struct {
    metav1.TypeMeta `json:",inline"`
    metav1.ListMeta `json:"metadata,omitempty"`
    Items           []Memcached `json:"items"`
}

func init() {
    SchemeBuilder.Register(&Memcached{}, &MemcachedList{})
}

generate crd with controller-tool


.PHONY: manifests
manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
    $(CONTROLLER_GEN) rbac:roleName=manager-role crd:crdVersions=v1,ignoreUnexportedFields=true,generateEmbeddedObjectMeta=false webhook paths="./..." output:crd:artifacts:config=config/crd/bases

crd

---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  annotations:
    controller-gen.kubebuilder.io/version: v0.16.2
  name: memcacheds.cache.example.com
spec:
  group: cache.example.com
  names:
    kind: Memcached
    listKind: MemcachedList
    plural: memcacheds
    singular: memcached
  scope: Namespaced
  versions:
  - name: v1alpha1
    schema:
      openAPIV3Schema:
        description: Memcached is the Schema for the memcacheds API
        properties:
          apiVersion:
            description: |-
              APIVersion defines the versioned schema of this representation of an object.
              Servers should convert recognized schemas to the latest internal value, and
              may reject unrecognized values.
              More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
            type: string
          kind:
            description: |-
              Kind is a string value representing the REST resource this object represents.
              Servers may infer this from the endpoint the client submits requests to.
              Cannot be updated.
              In CamelCase.
              More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
            type: string
          metadata:
            type: object
          spec:
            description: MemcachedSpec defines the desired state of Memcached
            properties:
              affinity:
                type: object
                x-kubernetes-preserve-unknown-fields: true
              podOverrides:
                type: object
                x-kubernetes-preserve-unknown-fields: true
            type: object
          status:
            description: MemcachedStatus defines the observed state of Memcached
            type: object
        type: object
    served: true
    storage: true
    subresources:
      status: {}

use json package to Unmarshal object

example CR

apiVersion: cache.example.com/v1alpha1
kind: Memcached
metadata:
  labels:
    app.kubernetes.io/name: foo
    app.kubernetes.io/managed-by: kustomize
  name: memcached-sample
spec:
  podOverrides:
    spec:
      securityContext:
        runAsUser: 1000

implemented controller logic


package controller

import (
    "context"
    "encoding/json"

    corev1 "k8s.io/api/core/v1"
    "k8s.io/apimachinery/pkg/runtime"
    ctrl "sigs.k8s.io/controller-runtime"
    "sigs.k8s.io/controller-runtime/pkg/client"
    "sigs.k8s.io/controller-runtime/pkg/log"

    cachev1alpha1 "github.com/whg517/memcached-operator/api/v1alpha1"
)

// MemcachedReconciler reconciles a Memcached object
type MemcachedReconciler struct {
    client.Client
    Scheme *runtime.Scheme
}

//+kubebuilder:rbac:groups=cache.example.com,resources=memcacheds,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=cache.example.com,resources=memcacheds/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=cache.example.com,resources=memcacheds/finalizers,verbs=update

func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    log := log.FromContext(ctx)
    obj := cachev1alpha1.Memcached{}

    if err := r.Get(ctx, req.NamespacedName, &obj); err != nil {
        if client.IgnoreNotFound(err) == nil {
            log.Info("Memcached resource not found. Ignoring since object must be deleted.")
            return ctrl.Result{}, nil
        }
        return ctrl.Result{}, err
    }

    podTemplate, err := convertRawExtension[corev1.PodTemplateSpec](obj.Spec.PodOverrides)
    if err != nil {
        return ctrl.Result{}, err
    }

    log.Info("Pod run as user is", "user", podTemplate.Spec.SecurityContext.RunAsUser)

    return ctrl.Result{}, nil
}

func convertRawExtension[T any](raw *runtime.RawExtension) (T, error) {
    var obj T
    if raw == nil || raw.Raw == nil {
        return obj, nil
    }

    if err := json.Unmarshal(raw.Raw, &obj); err != nil {
        return obj, err
    }
    return obj, nil
}

// SetupWithManager sets up the controller with the Manager.
func (r *MemcachedReconciler) SetupWithManager(mgr ctrl.Manager) error {
    return ctrl.NewControllerManagedBy(mgr).
        For(&cachev1alpha1.Memcached{}).
        Complete(r)
}
whg517 commented 1 month ago

@lwpk110 some helpful ref https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured