dynamo/deploy/operator/cmd/crd-apply/main.go

117 lines
2.7 KiB
Go

/*
* SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
package main
import (
"context"
"flag"
"fmt"
"os"
"path/filepath"
"strings"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/utils/ptr"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
"sigs.k8s.io/yaml"
)
const (
fieldManager = "dynamo-crd-apply"
versionAnnotation = "dynamo.nvidia.com/operator-version"
)
func main() {
crdsDir := flag.String("crds-dir", "/opt/dynamo-operator/crds/", "Directory containing CRD YAML files")
version := flag.String("version", "", "Operator version to stamp on CRDs")
flag.Parse()
ctrl.SetLogger(zap.New(zap.UseDevMode(true)))
log := ctrl.Log.WithName("crd-apply")
config, err := ctrl.GetConfig()
if err != nil {
log.Error(err, "unable to get kubernetes config")
os.Exit(1)
}
client, err := apiextensionsclient.NewForConfig(config)
if err != nil {
log.Error(err, "unable to create apiextensions client")
os.Exit(1)
}
entries, err := os.ReadDir(*crdsDir)
if err != nil {
log.Error(err, "unable to read CRDs directory", "dir", *crdsDir)
os.Exit(1)
}
ctx := context.Background()
var applied int
for _, entry := range entries {
if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".yaml") {
continue
}
filePath := filepath.Join(*crdsDir, entry.Name())
data, err := os.ReadFile(filePath)
if err != nil {
log.Error(err, "unable to read CRD file", "file", filePath)
os.Exit(1)
}
crd := &apiextensionsv1.CustomResourceDefinition{}
if err := yaml.Unmarshal(data, crd); err != nil {
log.Error(err, "unable to unmarshal CRD", "file", filePath)
os.Exit(1)
}
if *version != "" {
if crd.Annotations == nil {
crd.Annotations = make(map[string]string)
}
crd.Annotations[versionAnnotation] = *version
}
patchData, err := yaml.Marshal(crd)
if err != nil {
log.Error(err, "unable to marshal CRD for patch", "crd", crd.Name)
os.Exit(1)
}
_, err = client.ApiextensionsV1().CustomResourceDefinitions().Patch(
ctx,
crd.Name,
types.ApplyPatchType,
patchData,
metav1.PatchOptions{
FieldManager: fieldManager,
Force: ptr.To(true),
},
)
if err != nil {
log.Error(err, "unable to apply CRD", "crd", crd.Name)
os.Exit(1)
}
log.Info("Applied CRD", "crd", crd.Name)
applied++
}
if applied == 0 {
fmt.Fprintf(os.Stderr, "WARNING: no CRD files found in %s\n", *crdsDir)
os.Exit(1)
}
log.Info("CRD apply complete", "applied", applied)
}