From 8ea68c39787e4cef94b54d3129c0c774ec140ee4 Mon Sep 17 00:00:00 2001 From: Yunus Sandikci Date: Sun, 3 Dec 2023 16:20:53 +0300 Subject: [PATCH 01/12] . --- .apidoc.yaml | 6 ++ .golangci.yaml | 9 ++ cmd/benchmark/benchmark.go | 4 +- cmd/benchmark/main.go | 6 +- cmd/benchmark/types.go | 6 +- cmd/manager/main.go | 24 ++++- ...loud.spaceship.com_scheduledresources.yaml | 58 ++++++++++ devops.sh | 37 ++++++- docs/api.md | 76 +++++++++++++ examples/example.yaml | 18 ++++ pkg/apis/v1alpha1/groupversion_info.go | 20 ++++ pkg/apis/v1alpha1/scheduled_resource_types.go | 74 +++++++++++++ pkg/apis/v1alpha1/zz_generated.deepcopy.go | 98 +++++++++++++++++ pkg/{ => common}/config.go | 4 +- pkg/{ => common}/functions.go | 6 +- pkg/{ => common}/metrics.go | 2 +- pkg/common/scheduler.go | 99 +++++++++++++++++ pkg/controller.go | 102 ------------------ pkg/controllers/expiration.go | 95 ++++++++++++++++ pkg/controllers/scheduled_resource.go | 102 ++++++++++++++++++ pkg/scheduler.go | 85 --------------- 21 files changed, 721 insertions(+), 210 deletions(-) create mode 100644 .apidoc.yaml create mode 100644 deploy/crds/cloud.spaceship.com_scheduledresources.yaml create mode 100644 docs/api.md create mode 100644 examples/example.yaml create mode 100644 pkg/apis/v1alpha1/groupversion_info.go create mode 100644 pkg/apis/v1alpha1/scheduled_resource_types.go create mode 100644 pkg/apis/v1alpha1/zz_generated.deepcopy.go rename pkg/{ => common}/config.go (85%) rename pkg/{ => common}/functions.go (93%) rename pkg/{ => common}/metrics.go (97%) create mode 100644 pkg/common/scheduler.go delete mode 100644 pkg/controller.go create mode 100644 pkg/controllers/expiration.go create mode 100644 pkg/controllers/scheduled_resource.go delete mode 100644 pkg/scheduler.go diff --git a/.apidoc.yaml b/.apidoc.yaml new file mode 100644 index 0000000..68fe9ee --- /dev/null +++ b/.apidoc.yaml @@ -0,0 +1,6 @@ +processor: + ignoreTypes: + - "(.*)List$" + - "TypeMeta" +render: + kubernetesVersion: 1.25 diff --git a/.golangci.yaml b/.golangci.yaml index 1911340..46d7ace 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -9,6 +9,9 @@ linters: - gci # Disable gci import ordering checker since its buggy - depguard # Disallows to use non-listed packages - tagalign # Disallows to use non-aligned tags +linters-settings: + funlen: + lines: 90 issues: exclude-rules: - path: .*/metrics.go @@ -19,3 +22,9 @@ run: tests: false skip-dirs: - cmd/benchmark + skip-files: + - cmd/.*.go + - mocks/.*.go + - common/config.go + - .*/groupversion_info.go + - .*/zz_generated.deepcopy.go \ No newline at end of file diff --git a/cmd/benchmark/benchmark.go b/cmd/benchmark/benchmark.go index a35fd5f..39fb054 100644 --- a/cmd/benchmark/benchmark.go +++ b/cmd/benchmark/benchmark.go @@ -5,7 +5,7 @@ import ( "fmt" time "time" - "github.com/NCCloud/mayfly/pkg" + "github.com/NCCloud/mayfly/pkg/common" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -30,7 +30,7 @@ func (b *Benchmark) Listener() Result { kind := make(map[string]int) now := time.Now() for _, resourceKind := range b.config.Resources { - resourceList := pkg.NewResourceInstanceList(resourceKind) + resourceList := common.NewResourceInstanceList(resourceKind) resourcesListErr := b.mgrClient.List(context.Background(), resourceList) if resourcesListErr != nil { diff --git a/cmd/benchmark/main.go b/cmd/benchmark/main.go index bc5d1fd..8479645 100644 --- a/cmd/benchmark/main.go +++ b/cmd/benchmark/main.go @@ -5,7 +5,7 @@ import ( "os" "time" - "github.com/NCCloud/mayfly/pkg" + "github.com/NCCloud/mayfly/pkg/common" "github.com/go-echarts/go-echarts/v2/charts" "github.com/go-echarts/go-echarts/v2/opts" @@ -19,7 +19,7 @@ import ( ) var ( - config *pkg.Config + config *common.Config mgrClient client.Client pageTitle = "Mayfly Benchmark" benchmarkHtml = "mayfly_benchmark.html" @@ -29,7 +29,7 @@ func init() { scheme := runtime.NewScheme() utilruntime.Must(clientgoscheme.AddToScheme(scheme)) - config = pkg.NewConfig() + config = common.NewConfig() var mgrClientErr error mgrClient, mgrClientErr = client.New(ctrl.GetConfigOrDie(), client.Options{Scheme: scheme}) diff --git a/cmd/benchmark/types.go b/cmd/benchmark/types.go index bdd852e..dce2c7e 100644 --- a/cmd/benchmark/types.go +++ b/cmd/benchmark/types.go @@ -3,14 +3,14 @@ package main import ( "time" - "github.com/NCCloud/mayfly/pkg" + "github.com/NCCloud/mayfly/pkg/common" "sigs.k8s.io/controller-runtime/pkg/client" ) type Benchmark struct { granularity time.Duration - config *pkg.Config + config *common.Config mgrClient client.Client startedAt time.Time count int @@ -29,7 +29,7 @@ type Point struct { time time.Time } -func NewBenchmark(mgrClient client.Client, config *pkg.Config, count int) *Benchmark { +func NewBenchmark(mgrClient client.Client, config *common.Config, count int) *Benchmark { return &Benchmark{ granularity: 5 * time.Second, config: config, diff --git a/cmd/manager/main.go b/cmd/manager/main.go index 9e1ba3b..eb732ca 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -3,9 +3,14 @@ package main import ( "fmt" + "github.com/NCCloud/mayfly/pkg/apis/v1alpha1" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + + "github.com/NCCloud/mayfly/pkg/common" + "github.com/NCCloud/mayfly/pkg/controllers" + "sigs.k8s.io/controller-runtime/pkg/metrics/server" - "github.com/NCCloud/mayfly/pkg" "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/cache" @@ -21,7 +26,10 @@ const ( func main() { logger := zap.New() scheme := runtime.NewScheme() - config := pkg.NewConfig() + config := common.NewConfig() + + utilruntime.Must(v1alpha1.AddToScheme(scheme)) + ctrl.SetLogger(logger) logger.Info("Configuration", "config", config) @@ -43,14 +51,20 @@ func main() { } client := manager.GetClient() - scheduler := pkg.NewScheduler(config, client) + scheduler := common.NewScheduler(config, client) for _, resource := range config.Resources { - if err := pkg.NewController(config, client, resource, scheduler).SetupWithManager(manager); err != nil { - panic(err) + if expirationControllerErr := controllers.NewExpirationController(config, client, resource, scheduler). + SetupWithManager(manager); expirationControllerErr != nil { + panic(expirationControllerErr) } } + if scheduledResourceControllerErr := controllers.NewScheduledResourceController(config, client, scheduler). + SetupWithManager(manager); scheduledResourceControllerErr != nil { + panic(scheduledResourceControllerErr) + } + if addHealthCheckErr := manager.AddHealthzCheck("healthz", healthz.Ping); addHealthCheckErr != nil { panic(addHealthCheckErr) } diff --git a/deploy/crds/cloud.spaceship.com_scheduledresources.yaml b/deploy/crds/cloud.spaceship.com_scheduledresources.yaml new file mode 100644 index 0000000..7e80aad --- /dev/null +++ b/deploy/crds/cloud.spaceship.com_scheduledresources.yaml @@ -0,0 +1,58 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + name: scheduledresources.cloud.spaceship.com +spec: + group: cloud.spaceship.com + names: + kind: ScheduledResource + listKind: ScheduledResourceList + plural: scheduledresources + singular: scheduledresource + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + 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: + properties: + content: + type: string + in: + type: string + required: + - content + - in + type: object + status: + properties: + condition: + type: string + required: + - condition + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/devops.sh b/devops.sh index 79fcf84..842fe1b 100755 --- a/devops.sh +++ b/devops.sh @@ -1,13 +1,29 @@ #!/usr/bin/env bash +export CONTROLLER_GEN_VERSION="v0.13.0" export GOLANGCI_LINT_VERSION="v1.54.2" +export MOCKERY_GEN_VERSION="v2.36.0" +export GOFUMPT_VERSION="v0.5.0" +export TESTENV_VERSION="1.25.x!" prerequisites() { - if ! command -v golangci-lint &>/dev/null; then + if [[ "$(controller-gen --version 2>&1)" != *"$CONTROLLER_GEN_VERSION"* ]]; then + go install sigs.k8s.io/controller-tools/cmd/controller-gen@"${CONTROLLER_GEN_VERSION}" + fi + if [[ "$(golangci-lint --version 2>&1)" != *"$GOLANGCI_LINT_VERSION"* ]]; then go install github.com/golangci/golangci-lint/cmd/golangci-lint@"${GOLANGCI_LINT_VERSION}" fi - if ! command -v gofumpt &>/dev/null; then - go install mvdan.cc/gofumpt@latest + if [[ "$(mockery --version 2>&1)" != *"$MOCKERY_GEN_VERSION"* ]]; then + go install github.com/vektra/mockery/v2@"${MOCKERY_GEN_VERSION}" + fi + if [[ "$(gofumpt --version 2>&1)" != *"$GOFUMPT_VERSION"* ]]; then + go install mvdan.cc/gofumpt@"${GOFUMPT_VERSION}" + fi + if ! command -v crd-ref-docs &>/dev/null; then + go install github.com/elastic/crd-ref-docs@latest + fi + if ! command -v setup-envtest &>/dev/null; then + go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest fi } @@ -16,8 +32,21 @@ lint() { golangci-lint run --timeout=10m } +generate() { + rm -rf deploy/crds + controller-gen object paths="./..." + controller-gen crd paths="./..." output:dir=deploy/crds + sed '/Compiled/d' pkg/apis/v1alpha1/zz_generated.deepcopy.go > pkg/apis/v1alpha1/zz_generated.deepcopy.gotmp + mv pkg/apis/v1alpha1/zz_generated.deepcopy.gotmp pkg/apis/v1alpha1/zz_generated.deepcopy.go + crd-ref-docs --source-path=./pkg/apis --config .apidoc.yaml --renderer markdown --output-path=./docs/api.md +} + +install() { + kubectl apply -f deploy/crds +} + test() { - go test -v ./... + go test -v -coverpkg=./... ./... } prerequisites diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..c907cf9 --- /dev/null +++ b/docs/api.md @@ -0,0 +1,76 @@ +# API Reference + +## Packages +- [cloud.spaceship.com/v1alpha1](#cloudspaceshipcomv1alpha1) + + +## cloud.spaceship.com/v1alpha1 + +Package v1alpha1 contains API Schema definitions for the v1alpha1 API group + +### Resource Types +- [ScheduledResource](#scheduledresource) + + + +#### Condition + +_Underlying type:_ _string_ + + + +_Appears in:_ +- [ScheduledStatus](#scheduledstatus) + + + + + +#### ScheduledResource + + + + + + + +| Field | Description | +| --- | --- | +| `apiVersion` _string_ | `cloud.spaceship.com/v1alpha1` +| `kind` _string_ | `ScheduledResource` +| `kind` _string_ | 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 | +| `apiVersion` _string_ | 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 | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | +| `spec` _[ScheduledSpec](#scheduledspec)_ | | +| `status` _[ScheduledStatus](#scheduledstatus)_ | | + + +#### ScheduledSpec + + + + + +_Appears in:_ +- [ScheduledResource](#scheduledresource) + +| Field | Description | +| --- | --- | +| `in` _string_ | | +| `content` _string_ | | + + +#### ScheduledStatus + + + + + +_Appears in:_ +- [ScheduledResource](#scheduledresource) + +| Field | Description | +| --- | --- | +| `condition` _[Condition](#condition)_ | | + + diff --git a/examples/example.yaml b/examples/example.yaml new file mode 100644 index 0000000..b4d4b50 --- /dev/null +++ b/examples/example.yaml @@ -0,0 +1,18 @@ +apiVersion: cloud.spaceship.com/v1alpha1 +kind: ScheduledResource +metadata: + name: example + annotations: + mayfly.cloud.namecheap.com/expire: 30s +spec: + in: "15s" + content: | + apiVersion: v1 + kind: Secret + metadata: + name: example + namespace: default + annotations: + mayfly.cloud.namecheap.com/expire: 15s + data: + .secret-file: dmFsdWUtMg0KDQo= \ No newline at end of file diff --git a/pkg/apis/v1alpha1/groupversion_info.go b/pkg/apis/v1alpha1/groupversion_info.go new file mode 100644 index 0000000..8e5bb1f --- /dev/null +++ b/pkg/apis/v1alpha1/groupversion_info.go @@ -0,0 +1,20 @@ +// Package v1alpha1 contains API Schema definitions for the v1alpha1 API group +// +kubebuilder:object:generate=true +// +groupName=cloud.spaceship.com +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects. + GroupVersion = schema.GroupVersion{Group: "cloud.spaceship.com", Version: "v1alpha1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme. + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/pkg/apis/v1alpha1/scheduled_resource_types.go b/pkg/apis/v1alpha1/scheduled_resource_types.go new file mode 100644 index 0000000..0479d3b --- /dev/null +++ b/pkg/apis/v1alpha1/scheduled_resource_types.go @@ -0,0 +1,74 @@ +package v1alpha1 + +import ( + "errors" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/serializer/yaml" +) + +type ( + FailureReason string + Condition string +) + +const ( + ConditionCreated Condition = "Applied" + ConditionScheduled Condition = "Scheduled" + ConditionFailed Condition = "Failed" +) + +var ErrObjectIsNotValid = errors.New("object is not valid") + +func init() { + SchemeBuilder.Register(&ScheduledResource{}, &ScheduledResourceList{}) +} + +//+kubebuilder:object:root=true +//+kubebuilder:subresource:status +//+kubebuilder:printcolumn:name="Age",type=date,JSONPath=".metadata.creationTimestamp" + +type ScheduledResource struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ScheduledSpec `json:"spec,omitempty"` + Status ScheduledStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +type ScheduledResourceList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ScheduledResource `json:"items"` +} + +type ScheduledSpec struct { + In string `json:"in"` + Content string `json:"content"` +} + +type ScheduledStatus struct { + Condition Condition `json:"condition"` +} + +func (in *ScheduledResource) IsBeingDeleted() bool { + return in.DeletionTimestamp != nil +} + +func (in *ScheduledResource) ToUnstructured() (*unstructured.Unstructured, error) { + object, _, decodeErr := yaml.NewDecodingSerializer(unstructured.UnstructuredJSONScheme). + Decode([]byte(in.Spec.Content), nil, nil) + if decodeErr != nil { + return nil, decodeErr + } + + unstructuredObj, isUnstructuredObj := object.(*unstructured.Unstructured) + if !isUnstructuredObj { + return nil, ErrObjectIsNotValid + } + + return unstructuredObj, nil +} diff --git a/pkg/apis/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 0000000..eee17bf --- /dev/null +++ b/pkg/apis/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,98 @@ +//go:build !ignore_autogenerated + +// Code generated by controller-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScheduledResource) DeepCopyInto(out *ScheduledResource) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScheduledResource. +func (in *ScheduledResource) DeepCopy() *ScheduledResource { + if in == nil { + return nil + } + out := new(ScheduledResource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ScheduledResource) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScheduledResourceList) DeepCopyInto(out *ScheduledResourceList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ScheduledResource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScheduledResourceList. +func (in *ScheduledResourceList) DeepCopy() *ScheduledResourceList { + if in == nil { + return nil + } + out := new(ScheduledResourceList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ScheduledResourceList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScheduledSpec) DeepCopyInto(out *ScheduledSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScheduledSpec. +func (in *ScheduledSpec) DeepCopy() *ScheduledSpec { + if in == nil { + return nil + } + out := new(ScheduledSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScheduledStatus) DeepCopyInto(out *ScheduledStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScheduledStatus. +func (in *ScheduledStatus) DeepCopy() *ScheduledStatus { + if in == nil { + return nil + } + out := new(ScheduledStatus) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/config.go b/pkg/common/config.go similarity index 85% rename from pkg/config.go rename to pkg/common/config.go index 2f05666..c4ad137 100644 --- a/pkg/config.go +++ b/pkg/common/config.go @@ -1,4 +1,4 @@ -package pkg +package common import ( "time" @@ -10,7 +10,7 @@ type Config struct { EnableLeaderElection bool `env:"ENABLE_LEADER_ELECTION" envDefault:"false"` SyncPeriod *time.Duration `env:"SYNC_PERIOD" envDefault:"30m"` ExpirationLabel string `env:"EXPIRATION_LABEL" envDefault:"mayfly.cloud.namecheap.com/expire"` - Resources []string `env:"RESOURCES" envSeparator:"," envDefault:"v1;Secret"` + Resources []string `env:"RESOURCES" envSeparator:"," envDefault:"v1;Secret,cloud.spaceship.com/v1alpha1;ScheduledResource"` } func NewConfig() *Config { diff --git a/pkg/functions.go b/pkg/common/functions.go similarity index 93% rename from pkg/functions.go rename to pkg/common/functions.go index 02a3f38..b7f2a5c 100644 --- a/pkg/functions.go +++ b/pkg/common/functions.go @@ -1,4 +1,4 @@ -package pkg +package common import ( "fmt" @@ -30,7 +30,7 @@ func NewResourceInstance(apiVersionKind string) *unstructured.Unstructured { apiVersionKindArr := strings.Split(apiVersionKind, ";") return &unstructured.Unstructured{ - Object: map[string]interface{}{ + Object: map[string]any{ "apiVersion": apiVersionKindArr[0], "kind": apiVersionKindArr[1], }, @@ -41,7 +41,7 @@ func NewResourceInstanceList(apiVersionKind string) *unstructured.UnstructuredLi resourceInstance := NewResourceInstance(apiVersionKind) return &unstructured.UnstructuredList{ - Object: map[string]interface{}{ + Object: map[string]any{ "apiVersion": resourceInstance.GetAPIVersion(), "kind": fmt.Sprintf("%sList", resourceInstance.GetKind()), }, diff --git a/pkg/metrics.go b/pkg/common/metrics.go similarity index 97% rename from pkg/metrics.go rename to pkg/common/metrics.go index f657347..31ee926 100644 --- a/pkg/metrics.go +++ b/pkg/common/metrics.go @@ -1,4 +1,4 @@ -package pkg +package common import ( "github.com/prometheus/client_golang/prometheus" diff --git a/pkg/common/scheduler.go b/pkg/common/scheduler.go new file mode 100644 index 0000000..8e340ee --- /dev/null +++ b/pkg/common/scheduler.go @@ -0,0 +1,99 @@ +package common + +import ( + "fmt" + "time" + + "github.com/NCCloud/mayfly/pkg/apis/v1alpha1" + + "github.com/go-co-op/gocron" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +const MonitoringInterval = "5s" + +type Scheduler struct { + config *Config + client client.Client + scheduler *gocron.Scheduler +} + +func NewScheduler(config *Config, client client.Client) *Scheduler { + scheduler := &Scheduler{ + config: config, + client: client, + scheduler: gocron.NewScheduler(time.UTC), + } + + scheduler.startMonitoring() + scheduler.scheduler.StartAsync() + + return scheduler +} + +func (s *Scheduler) CreateOrUpdateCreationJob(date time.Time, + task func(resource v1alpha1.ScheduledResource) error, resource v1alpha1.ScheduledResource, +) error { + tag := fmt.Sprintf("%v-create", resource.GetUID()) + + if jobs, _ := s.scheduler.FindJobsByTag(tag); len(jobs) > 0 { + if jobs[0].NextRun().Equal(date) { + return nil + } + + if removeJobErr := s.scheduler.RemoveByTag(tag); removeJobErr != nil { + return removeJobErr + } + } + + _, jobErr := s.scheduler.StartAt(date).Every(1).LimitRunsTo(1).Tag(tag). + Do(task, resource) + + return jobErr +} + +func (s *Scheduler) CreateOrUpdateExpirationJob(date time.Time, + task func(resource client.Object) error, resource client.Object, +) error { + tag := fmt.Sprintf("%v-expire", resource.GetUID()) + + if jobs, _ := s.scheduler.FindJobsByTag(tag); len(jobs) > 0 { + if jobs[0].NextRun().Equal(date) { + return nil + } + + if removeJobErr := s.scheduler.RemoveByTag(tag); removeJobErr != nil { + return removeJobErr + } + } + + _, jobErr := s.scheduler.StartAt(date).Every(1).LimitRunsTo(1).Tag(tag). + Do(task, resource) + + return jobErr +} + +func (s *Scheduler) RemoveCreationJob(resource client.Object) error { + return s.scheduler.RemoveByTag(fmt.Sprintf("%v-create", resource.GetUID())) +} + +func (s *Scheduler) RemoveExpirationJob(resource client.Object) error { + return s.scheduler.RemoveByTag(fmt.Sprintf("%v-expire", resource.GetUID())) +} + +func (s *Scheduler) startMonitoring() { + if _, doErr := s.scheduler.Every(MonitoringInterval).Do(func() { + fmt.Printf("\n\n\nJob Count: %d\n\n\n", len(s.scheduler.Jobs())) + exportMayflyTotalJobsMetrics(float64(len(s.scheduler.Jobs()))) + + pastJobs := 0 + for _, job := range s.scheduler.Jobs() { + if job.NextRun().Before(time.Now()) { + pastJobs++ + } + } + exportMayflyPastJobsMetrics(float64(pastJobs)) + }); doErr != nil { + panic(doErr) + } +} diff --git a/pkg/controller.go b/pkg/controller.go deleted file mode 100644 index 3901c96..0000000 --- a/pkg/controller.go +++ /dev/null @@ -1,102 +0,0 @@ -package pkg - -import ( - "context" - "fmt" - - "k8s.io/apimachinery/pkg/api/errors" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/event" - "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/predicate" -) - -type Controller struct { - APIVersionKind string - Config *Config - MgrClient client.Client - Scheduler *Scheduler -} - -func NewController(config *Config, client client.Client, apiVersionKind string, scheduler *Scheduler) *Controller { - return &Controller{ - APIVersionKind: apiVersionKind, - Config: config, - MgrClient: client, - Scheduler: scheduler, - } -} - -func (r *Controller) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - logger := log.FromContext(ctx) - logger.Info("Reconciliation started.") - - resource := NewResourceInstance(r.APIVersionKind) - - if getErr := r.MgrClient.Get(ctx, req.NamespacedName, resource); getErr != nil { - if errors.IsNotFound(getErr) { - _ = r.Scheduler.RemoveJob(fmt.Sprintf("%v", resource.GetUID())) - - return ctrl.Result{}, nil - } - - return ctrl.Result{}, getErr - } - - hasExpired, expirationDate, hasExpiredErr := IsExpired(resource, r.Config) - if hasExpiredErr != nil { - logger.Error(hasExpiredErr, "Error while checking if resource has expired.") - - return ctrl.Result{}, hasExpiredErr - } - - if hasExpired { - logger.Info("Resource already expired. Removing") - - _ = r.MgrClient.Delete(ctx, resource) - - _ = r.Scheduler.RemoveJob(fmt.Sprintf("%v", resource.GetUID())) - - return ctrl.Result{}, nil - } - - startJobErr := r.Scheduler.StartOrUpdateJob(ctx, expirationDate, func(ctx context.Context, client client.Client, - resource client.Object, - ) error { - return r.MgrClient.Delete(ctx, resource) - }, r.MgrClient, resource) - if startJobErr != nil { - logger.Error(startJobErr, "Error while starting job.") - - return ctrl.Result{}, startJobErr - } - - return ctrl.Result{}, nil -} - -func (r *Controller) SetupWithManager(mgr ctrl.Manager) error { - return ctrl.NewControllerManagedBy(mgr). - For(NewResourceInstance(r.APIVersionKind)). - WithEventFilter(predicate.Funcs{ - CreateFunc: func(createEvent event.CreateEvent) bool { - mayFlyAnnotation := createEvent.Object.GetAnnotations()[r.Config.ExpirationLabel] - - return mayFlyAnnotation != "" - }, - DeleteFunc: func(deleteEvent event.DeleteEvent) bool { - mayFlyAnnotation := deleteEvent.Object.GetAnnotations()[r.Config.ExpirationLabel] - - return mayFlyAnnotation != "" - }, - UpdateFunc: func(updateEvent event.UpdateEvent) bool { - oldMayFlyAnnotation := updateEvent.ObjectOld.GetAnnotations()[r.Config.ExpirationLabel] - newMayFlyAnnotation := updateEvent.ObjectNew.GetAnnotations()[r.Config.ExpirationLabel] - if newMayFlyAnnotation != "" && oldMayFlyAnnotation != newMayFlyAnnotation { - return true - } - - return false - }, - }).Complete(r) -} diff --git a/pkg/controllers/expiration.go b/pkg/controllers/expiration.go new file mode 100644 index 0000000..f8ccb6b --- /dev/null +++ b/pkg/controllers/expiration.go @@ -0,0 +1,95 @@ +package controllers + +import ( + "context" + + "github.com/NCCloud/mayfly/pkg/common" + + "k8s.io/apimachinery/pkg/api/errors" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/event" + "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/predicate" +) + +type ExpirationController struct { + config *common.Config + client client.Client + scheduler *common.Scheduler + apiVersionKind string +} + +func NewExpirationController(config *common.Config, client client.Client, + apiVersionKind string, scheduler *common.Scheduler, +) *ExpirationController { + return &ExpirationController{ + config: config, + client: client, + scheduler: scheduler, + apiVersionKind: apiVersionKind, + } +} + +func (r *ExpirationController) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + var ( + logger = log.FromContext(ctx) + resource = common.NewResourceInstance(r.apiVersionKind) + ) + + logger.Info("Reconciliation started.") + + if getErr := r.client.Get(ctx, req.NamespacedName, resource); getErr != nil { + if errors.IsNotFound(getErr) { + _ = r.scheduler.RemoveExpirationJob(resource) + } + + return ctrl.Result{}, client.IgnoreNotFound(getErr) + } + + hasExpired, expirationDate, hasExpiredErr := common.IsExpired(resource, r.config) + if hasExpiredErr != nil { + logger.Error(hasExpiredErr, "Error while checking if resource has expired.") + + return ctrl.Result{}, hasExpiredErr + } + + if hasExpired { + logger.Info("Resource already expired. Removing") + + _ = r.client.Delete(ctx, resource) + _ = r.scheduler.RemoveExpirationJob(resource) + + return ctrl.Result{}, nil + } + + if createOrUpdateErr := r.scheduler.CreateOrUpdateExpirationJob(expirationDate, + func(resource client.Object) error { + return r.client.Delete(context.Background(), resource) + }, resource); createOrUpdateErr != nil { + logger.Error(createOrUpdateErr, "Error while starting job.") + + return ctrl.Result{}, createOrUpdateErr + } + + return ctrl.Result{}, nil +} + +func (r *ExpirationController) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(common.NewResourceInstance(r.apiVersionKind)). + WithEventFilter(predicate.Funcs{ + CreateFunc: func(createEvent event.CreateEvent) bool { + return len(createEvent.Object.GetAnnotations()[r.config.ExpirationLabel]) != 0 + }, + DeleteFunc: func(deleteEvent event.DeleteEvent) bool { + return len(deleteEvent.Object.GetAnnotations()[r.config.ExpirationLabel]) != 0 + }, + UpdateFunc: func(updateEvent event.UpdateEvent) bool { + oldMayFlyAnnotation := updateEvent.ObjectOld.GetAnnotations()[r.config.ExpirationLabel] + newMayFlyAnnotation := updateEvent.ObjectNew.GetAnnotations()[r.config.ExpirationLabel] + + return len(newMayFlyAnnotation) != 0 && oldMayFlyAnnotation != newMayFlyAnnotation + }, + }).Complete(r) +} diff --git a/pkg/controllers/scheduled_resource.go b/pkg/controllers/scheduled_resource.go new file mode 100644 index 0000000..42e6ce1 --- /dev/null +++ b/pkg/controllers/scheduled_resource.go @@ -0,0 +1,102 @@ +package controllers + +import ( + "context" + errors2 "errors" + "time" + + "k8s.io/apimachinery/pkg/api/errors" + + "github.com/NCCloud/mayfly/pkg/apis/v1alpha1" + "github.com/NCCloud/mayfly/pkg/common" + + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" +) + +type ScheduledResourceController struct { + config *common.Config + client client.Client + scheduler *common.Scheduler +} + +func NewScheduledResourceController(config *common.Config, client client.Client, + scheduler *common.Scheduler, +) *ScheduledResourceController { + return &ScheduledResourceController{ + config: config, + client: client, + scheduler: scheduler, + } +} + +func (r *ScheduledResourceController) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + var ( + logger = log.FromContext(ctx) + scheduledResource = &v1alpha1.ScheduledResource{} + ) + + if getErr := r.client.Get(ctx, req.NamespacedName, scheduledResource); getErr != nil { + if errors.IsNotFound(getErr) { + _ = r.scheduler.RemoveCreationJob(scheduledResource) + } + + return ctrl.Result{}, client.IgnoreNotFound(getErr) + } + + logger.Info("Reconciliation started.") + + if scheduledResource.Status.Condition == v1alpha1.ConditionCreated { + return ctrl.Result{}, nil + } + + duration, parseDurationErr := time.ParseDuration(scheduledResource.Spec.In) + if parseDurationErr != nil { + return ctrl.Result{}, parseDurationErr + } + + if createOrUpdateErr := r.scheduler.CreateOrUpdateCreationJob(scheduledResource.CreationTimestamp.Add(duration), + func(resource v1alpha1.ScheduledResource) error { + unstructured, toUnstructuredErr := resource.ToUnstructured() + if toUnstructuredErr != nil { + return toUnstructuredErr + } + + if getErr := r.client.Get(context.Background(), + client.ObjectKeyFromObject(&resource), &resource); getErr != nil { + return getErr + } + + if createErr := r.client.Create(context.Background(), + unstructured); client.IgnoreAlreadyExists(createErr) != nil { + resource.Status.Condition = v1alpha1.ConditionFailed + + return errors2.Join(createErr, r.client.Status().Update(context.Background(), &resource)) + } + + logger.Info("%s/%s applied", resource.Name, resource.Namespace) + + if removeErr := r.scheduler.RemoveCreationJob(&resource); removeErr != nil { + return removeErr + } + + resource.Status.Condition = v1alpha1.ConditionCreated + + return r.client.Status().Update(context.Background(), &resource) + }, *scheduledResource); createOrUpdateErr != nil { + return ctrl.Result{}, createOrUpdateErr + } + + logger.Info("Reconciliation finished.") + + scheduledResource.Status.Condition = v1alpha1.ConditionScheduled + + return ctrl.Result{}, r.client.Status().Update(ctx, scheduledResource) +} + +func (r *ScheduledResourceController) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&v1alpha1.ScheduledResource{}). + Complete(r) +} diff --git a/pkg/scheduler.go b/pkg/scheduler.go deleted file mode 100644 index 232697d..0000000 --- a/pkg/scheduler.go +++ /dev/null @@ -1,85 +0,0 @@ -package pkg - -import ( - "context" - "fmt" - "time" - - "github.com/go-co-op/gocron" - "sigs.k8s.io/controller-runtime/pkg/client" -) - -type Scheduler struct { - Config *Config - Client client.Client - CronScheduler *gocron.Scheduler -} - -func NewScheduler(config *Config, client client.Client) *Scheduler { - cronScheduler := gocron.NewScheduler(time.UTC) - cronScheduler.StartAsync() - - scheduler := &Scheduler{ - Config: config, - Client: client, - CronScheduler: cronScheduler, - } - - scheduler.startMonitoring() - - return scheduler -} - -func (s *Scheduler) startMonitoring() { - const granularity = 5 * time.Second - - go func() { - for { - exportMayflyTotalJobsMetrics(float64(len(s.CronScheduler.Jobs()))) - - pastJobs := 0 - - for _, job := range s.CronScheduler.Jobs() { - if job.NextRun().Before(time.Now()) { - pastJobs++ - } - } - - exportMayflyPastJobsMetrics(float64(pastJobs)) - time.Sleep(granularity) - } - }() -} - -func (s *Scheduler) StartOrUpdateJob(ctx context.Context, expirationDate time.Time, - task func(ctx context.Context, client client.Client, resource client.Object) error, - client client.Client, resource client.Object, -) error { - jobs, _ := s.CronScheduler.FindJobsByTag(fmt.Sprintf("%v", resource.GetUID())) - - if len(jobs) > 0 { - jobExpirationDate := jobs[0].NextRun() - if jobExpirationDate.Equal(expirationDate) { - return nil - } - - _ = s.RemoveJob(fmt.Sprintf("%v", resource.GetUID())) - } - - _, jobErr := s.CronScheduler. - Every(1). - LimitRunsTo(1). - StartAt(expirationDate). - Tag(fmt.Sprintf("%v", resource.GetUID())). - Do(task, ctx, client, resource) - - if jobErr != nil { - return jobErr - } - - return nil -} - -func (s *Scheduler) RemoveJob(id string) error { - return s.CronScheduler.RemoveByTag(id) -} From 1f3d811df4b720e13b53b597d365699471afc36f Mon Sep 17 00:00:00 2001 From: Yunus Sandikci Date: Sun, 3 Dec 2023 22:21:26 +0300 Subject: [PATCH 02/12] . --- pkg/apis/v1alpha1/scheduled_resource_types.go | 2 +- pkg/common/scheduler.go | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/apis/v1alpha1/scheduled_resource_types.go b/pkg/apis/v1alpha1/scheduled_resource_types.go index 0479d3b..2d50861 100644 --- a/pkg/apis/v1alpha1/scheduled_resource_types.go +++ b/pkg/apis/v1alpha1/scheduled_resource_types.go @@ -14,7 +14,7 @@ type ( ) const ( - ConditionCreated Condition = "Applied" + ConditionCreated Condition = "Created" ConditionScheduled Condition = "Scheduled" ConditionFailed Condition = "Failed" ) diff --git a/pkg/common/scheduler.go b/pkg/common/scheduler.go index 8e340ee..c1f61f0 100644 --- a/pkg/common/scheduler.go +++ b/pkg/common/scheduler.go @@ -83,7 +83,6 @@ func (s *Scheduler) RemoveExpirationJob(resource client.Object) error { func (s *Scheduler) startMonitoring() { if _, doErr := s.scheduler.Every(MonitoringInterval).Do(func() { - fmt.Printf("\n\n\nJob Count: %d\n\n\n", len(s.scheduler.Jobs())) exportMayflyTotalJobsMetrics(float64(len(s.scheduler.Jobs()))) pastJobs := 0 From 90a9ace1b2a5738ce38d07e08a9e766d70a493e8 Mon Sep 17 00:00:00 2001 From: Yunus Sandikci Date: Sun, 3 Dec 2023 22:22:31 +0300 Subject: [PATCH 03/12] . --- ...ces.yaml => cloud.namecheap.com_scheduledresources.yaml} | 4 ++-- docs/api.md | 6 +++--- examples/example.yaml | 2 +- pkg/apis/v1alpha1/groupversion_info.go | 4 ++-- pkg/common/config.go | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) rename deploy/crds/{cloud.spaceship.com_scheduledresources.yaml => cloud.namecheap.com_scheduledresources.yaml} (95%) diff --git a/deploy/crds/cloud.spaceship.com_scheduledresources.yaml b/deploy/crds/cloud.namecheap.com_scheduledresources.yaml similarity index 95% rename from deploy/crds/cloud.spaceship.com_scheduledresources.yaml rename to deploy/crds/cloud.namecheap.com_scheduledresources.yaml index 7e80aad..d6e237a 100644 --- a/deploy/crds/cloud.spaceship.com_scheduledresources.yaml +++ b/deploy/crds/cloud.namecheap.com_scheduledresources.yaml @@ -4,9 +4,9 @@ kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.13.0 - name: scheduledresources.cloud.spaceship.com + name: scheduledresources.cloud.namecheap.com spec: - group: cloud.spaceship.com + group: cloud.namecheap.com names: kind: ScheduledResource listKind: ScheduledResourceList diff --git a/docs/api.md b/docs/api.md index c907cf9..d8e0a7e 100644 --- a/docs/api.md +++ b/docs/api.md @@ -1,10 +1,10 @@ # API Reference ## Packages -- [cloud.spaceship.com/v1alpha1](#cloudspaceshipcomv1alpha1) +- [cloud.namecheap.com/v1alpha1](#cloudnamecheapcomv1alpha1) -## cloud.spaceship.com/v1alpha1 +## cloud.namecheap.com/v1alpha1 Package v1alpha1 contains API Schema definitions for the v1alpha1 API group @@ -36,7 +36,7 @@ _Appears in:_ | Field | Description | | --- | --- | -| `apiVersion` _string_ | `cloud.spaceship.com/v1alpha1` +| `apiVersion` _string_ | `cloud.namecheap.com/v1alpha1` | `kind` _string_ | `ScheduledResource` | `kind` _string_ | 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 | | `apiVersion` _string_ | 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 | diff --git a/examples/example.yaml b/examples/example.yaml index b4d4b50..cf38b4f 100644 --- a/examples/example.yaml +++ b/examples/example.yaml @@ -1,4 +1,4 @@ -apiVersion: cloud.spaceship.com/v1alpha1 +apiVersion: cloud.namecheap.com/v1alpha1 kind: ScheduledResource metadata: name: example diff --git a/pkg/apis/v1alpha1/groupversion_info.go b/pkg/apis/v1alpha1/groupversion_info.go index 8e5bb1f..d742ebb 100644 --- a/pkg/apis/v1alpha1/groupversion_info.go +++ b/pkg/apis/v1alpha1/groupversion_info.go @@ -1,6 +1,6 @@ // Package v1alpha1 contains API Schema definitions for the v1alpha1 API group // +kubebuilder:object:generate=true -// +groupName=cloud.spaceship.com +// +groupName=cloud.namecheap.com package v1alpha1 import ( @@ -10,7 +10,7 @@ import ( var ( // GroupVersion is group version used to register these objects. - GroupVersion = schema.GroupVersion{Group: "cloud.spaceship.com", Version: "v1alpha1"} + GroupVersion = schema.GroupVersion{Group: "cloud.namecheap.com", Version: "v1alpha1"} // SchemeBuilder is used to add go types to the GroupVersionKind scheme. SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} diff --git a/pkg/common/config.go b/pkg/common/config.go index c4ad137..752d01a 100644 --- a/pkg/common/config.go +++ b/pkg/common/config.go @@ -10,7 +10,7 @@ type Config struct { EnableLeaderElection bool `env:"ENABLE_LEADER_ELECTION" envDefault:"false"` SyncPeriod *time.Duration `env:"SYNC_PERIOD" envDefault:"30m"` ExpirationLabel string `env:"EXPIRATION_LABEL" envDefault:"mayfly.cloud.namecheap.com/expire"` - Resources []string `env:"RESOURCES" envSeparator:"," envDefault:"v1;Secret,cloud.spaceship.com/v1alpha1;ScheduledResource"` + Resources []string `env:"RESOURCES" envSeparator:"," envDefault:"v1;Secret,cloud.namecheap.com/v1alpha1;ScheduledResource"` } func NewConfig() *Config { From 9e59d7f54b3c46635fee0bcd0848b4274e72cc80 Mon Sep 17 00:00:00 2001 From: Yunus Sandikci Date: Sun, 3 Dec 2023 22:53:25 +0300 Subject: [PATCH 04/12] Update scheduled_resource.go --- pkg/controllers/scheduled_resource.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/controllers/scheduled_resource.go b/pkg/controllers/scheduled_resource.go index 42e6ce1..4b56156 100644 --- a/pkg/controllers/scheduled_resource.go +++ b/pkg/controllers/scheduled_resource.go @@ -3,6 +3,7 @@ package controllers import ( "context" errors2 "errors" + "fmt" "time" "k8s.io/apimachinery/pkg/api/errors" @@ -75,7 +76,7 @@ func (r *ScheduledResourceController) Reconcile(ctx context.Context, req ctrl.Re return errors2.Join(createErr, r.client.Status().Update(context.Background(), &resource)) } - logger.Info("%s/%s applied", resource.Name, resource.Namespace) + logger.Info(fmt.Sprintf("%s/%s created", resource.Name, resource.Namespace)) if removeErr := r.scheduler.RemoveCreationJob(&resource); removeErr != nil { return removeErr From c539df37165217b73e64efa9b31653d5510d18af Mon Sep 17 00:00:00 2001 From: Yunus Sandikci Date: Mon, 4 Dec 2023 11:03:25 +0300 Subject: [PATCH 05/12] . --- pkg/common/config.go | 1 + pkg/common/scheduler.go | 15 +++++++-------- pkg/common/{functions.go => utils.go} | 0 pkg/controllers/expiration.go | 6 +++--- pkg/controllers/scheduled_resource.go | 6 +++--- 5 files changed, 14 insertions(+), 14 deletions(-) rename pkg/common/{functions.go => utils.go} (100%) diff --git a/pkg/common/config.go b/pkg/common/config.go index 752d01a..ea2b21e 100644 --- a/pkg/common/config.go +++ b/pkg/common/config.go @@ -9,6 +9,7 @@ import ( type Config struct { EnableLeaderElection bool `env:"ENABLE_LEADER_ELECTION" envDefault:"false"` SyncPeriod *time.Duration `env:"SYNC_PERIOD" envDefault:"30m"` + MonitoringInterval *time.Duration `env:"MONITORING_INTERVAL" envDefault:"5s"` ExpirationLabel string `env:"EXPIRATION_LABEL" envDefault:"mayfly.cloud.namecheap.com/expire"` Resources []string `env:"RESOURCES" envSeparator:"," envDefault:"v1;Secret,cloud.namecheap.com/v1alpha1;ScheduledResource"` } diff --git a/pkg/common/scheduler.go b/pkg/common/scheduler.go index c1f61f0..4a806c0 100644 --- a/pkg/common/scheduler.go +++ b/pkg/common/scheduler.go @@ -10,8 +10,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -const MonitoringInterval = "5s" - type Scheduler struct { config *Config client client.Client @@ -52,10 +50,10 @@ func (s *Scheduler) CreateOrUpdateCreationJob(date time.Time, return jobErr } -func (s *Scheduler) CreateOrUpdateExpirationJob(date time.Time, +func (s *Scheduler) CreateOrUpdateDeletionJob(date time.Time, task func(resource client.Object) error, resource client.Object, ) error { - tag := fmt.Sprintf("%v-expire", resource.GetUID()) + tag := fmt.Sprintf("%v-delete", resource.GetUID()) if jobs, _ := s.scheduler.FindJobsByTag(tag); len(jobs) > 0 { if jobs[0].NextRun().Equal(date) { @@ -73,16 +71,16 @@ func (s *Scheduler) CreateOrUpdateExpirationJob(date time.Time, return jobErr } -func (s *Scheduler) RemoveCreationJob(resource client.Object) error { +func (s *Scheduler) DeleteCreationJob(resource client.Object) error { return s.scheduler.RemoveByTag(fmt.Sprintf("%v-create", resource.GetUID())) } -func (s *Scheduler) RemoveExpirationJob(resource client.Object) error { - return s.scheduler.RemoveByTag(fmt.Sprintf("%v-expire", resource.GetUID())) +func (s *Scheduler) DeleteDeletionJob(resource client.Object) error { + return s.scheduler.RemoveByTag(fmt.Sprintf("%v-delete", resource.GetUID())) } func (s *Scheduler) startMonitoring() { - if _, doErr := s.scheduler.Every(MonitoringInterval).Do(func() { + if _, doErr := s.scheduler.SingletonMode().Every(s.config.MonitoringInterval).Do(func() { exportMayflyTotalJobsMetrics(float64(len(s.scheduler.Jobs()))) pastJobs := 0 @@ -91,6 +89,7 @@ func (s *Scheduler) startMonitoring() { pastJobs++ } } + exportMayflyPastJobsMetrics(float64(pastJobs)) }); doErr != nil { panic(doErr) diff --git a/pkg/common/functions.go b/pkg/common/utils.go similarity index 100% rename from pkg/common/functions.go rename to pkg/common/utils.go diff --git a/pkg/controllers/expiration.go b/pkg/controllers/expiration.go index f8ccb6b..a7732be 100644 --- a/pkg/controllers/expiration.go +++ b/pkg/controllers/expiration.go @@ -41,7 +41,7 @@ func (r *ExpirationController) Reconcile(ctx context.Context, req ctrl.Request) if getErr := r.client.Get(ctx, req.NamespacedName, resource); getErr != nil { if errors.IsNotFound(getErr) { - _ = r.scheduler.RemoveExpirationJob(resource) + _ = r.scheduler.DeleteDeletionJob(resource) } return ctrl.Result{}, client.IgnoreNotFound(getErr) @@ -58,12 +58,12 @@ func (r *ExpirationController) Reconcile(ctx context.Context, req ctrl.Request) logger.Info("Resource already expired. Removing") _ = r.client.Delete(ctx, resource) - _ = r.scheduler.RemoveExpirationJob(resource) + _ = r.scheduler.DeleteDeletionJob(resource) return ctrl.Result{}, nil } - if createOrUpdateErr := r.scheduler.CreateOrUpdateExpirationJob(expirationDate, + if createOrUpdateErr := r.scheduler.CreateOrUpdateDeletionJob(expirationDate, func(resource client.Object) error { return r.client.Delete(context.Background(), resource) }, resource); createOrUpdateErr != nil { diff --git a/pkg/controllers/scheduled_resource.go b/pkg/controllers/scheduled_resource.go index 4b56156..77e8752 100644 --- a/pkg/controllers/scheduled_resource.go +++ b/pkg/controllers/scheduled_resource.go @@ -40,7 +40,7 @@ func (r *ScheduledResourceController) Reconcile(ctx context.Context, req ctrl.Re if getErr := r.client.Get(ctx, req.NamespacedName, scheduledResource); getErr != nil { if errors.IsNotFound(getErr) { - _ = r.scheduler.RemoveCreationJob(scheduledResource) + _ = r.scheduler.DeleteCreationJob(scheduledResource) } return ctrl.Result{}, client.IgnoreNotFound(getErr) @@ -76,9 +76,9 @@ func (r *ScheduledResourceController) Reconcile(ctx context.Context, req ctrl.Re return errors2.Join(createErr, r.client.Status().Update(context.Background(), &resource)) } - logger.Info(fmt.Sprintf("%s/%s created", resource.Name, resource.Namespace)) + logger.Info(fmt.Sprintf("%s/%s created.", resource.Name, resource.Namespace)) - if removeErr := r.scheduler.RemoveCreationJob(&resource); removeErr != nil { + if removeErr := r.scheduler.DeleteCreationJob(&resource); removeErr != nil { return removeErr } From 9dd539335805021a12541c544d5f3a9e7b8765c3 Mon Sep 17 00:00:00 2001 From: Goncalo Lourenco Date: Mon, 4 Dec 2023 10:09:38 +0000 Subject: [PATCH 06/12] Added a human description for the Sheduled Resource Creation --- README.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/README.md b/README.md index ef6fbeb..1e75d63 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,9 @@ export RESOURCES="v1;Secret,test.com/v1alpha;MyCRD" ``` ## 🚀 Usage + +### Resouce Expiration + Once you have determined which resources you want Mayfly to monitor, you can set the `mayfly.cloud.namecheap.com/expire` annotation on those resources with a duration value. This will cause Mayfly to delete the resources once the specified duration has passed, based on the time of their creation. Keep in mind that the expiration will be calculated based on the creation time of the resource. @@ -43,6 +46,35 @@ spec: - infinity ``` +### Scheduled Resource Creation + +The ScheduledResource CRD allows you to schedule the creation of an object in the future. This can be combined with the expire annotation, enabling Mayfly to create and remove certain objects for a temporary period in the future. + +Example: +``` +apiVersion: cloud.namecheap.com/v1alpha1 +kind: ScheduledResource +metadata: + annotations: + mayfly.cloud.namecheap.com/expire: 60m + name: example + namespace: default +spec: + in: 30m + content: | + apiVersion: v1 + kind: Secret + metadata: + name: example + namespace: default + annotations: + mayfly.cloud.namecheap.com/expire: 30m + data: + .secret-file: dmFsdWUtMg0KDQo= +status: + condition: Scheduled +``` +This feature is particularly useful for setting up temporary resources that are only needed for a short period, reducing clutter and improving the efficiency of resource management. ## 🛳️ Deployment From 72b2187fddcaa50f1888fdfd862f456df67c11a8 Mon Sep 17 00:00:00 2001 From: Yunus Sandikci Date: Thu, 14 Dec 2023 18:15:58 +0300 Subject: [PATCH 07/12] minor changes. --- cmd/manager/main.go | 2 +- pkg/common/config.go | 10 +++++----- pkg/common/scheduler.go | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cmd/manager/main.go b/cmd/manager/main.go index eb732ca..afb416d 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -43,7 +43,7 @@ func main() { LeaderElection: config.EnableLeaderElection, LeaderElectionID: "mayfly-leader.cloud.namecheap.com", Cache: cache.Options{ - SyncPeriod: config.SyncPeriod, + SyncPeriod: &config.SyncPeriod, }, }) if managerErr != nil { diff --git a/pkg/common/config.go b/pkg/common/config.go index ea2b21e..fdb4068 100644 --- a/pkg/common/config.go +++ b/pkg/common/config.go @@ -7,11 +7,11 @@ import ( ) type Config struct { - EnableLeaderElection bool `env:"ENABLE_LEADER_ELECTION" envDefault:"false"` - SyncPeriod *time.Duration `env:"SYNC_PERIOD" envDefault:"30m"` - MonitoringInterval *time.Duration `env:"MONITORING_INTERVAL" envDefault:"5s"` - ExpirationLabel string `env:"EXPIRATION_LABEL" envDefault:"mayfly.cloud.namecheap.com/expire"` - Resources []string `env:"RESOURCES" envSeparator:"," envDefault:"v1;Secret,cloud.namecheap.com/v1alpha1;ScheduledResource"` + EnableLeaderElection bool `env:"ENABLE_LEADER_ELECTION" envDefault:"false"` + SyncPeriod time.Duration `env:"SYNC_PERIOD" envDefault:"30m"` + MonitoringInterval time.Duration `env:"MONITORING_INTERVAL" envDefault:"5s"` + ExpirationLabel string `env:"EXPIRATION_LABEL" envDefault:"mayfly.cloud.namecheap.com/expire"` + Resources []string `env:"RESOURCES" envSeparator:"," envDefault:"v1;Secret,cloud.namecheap.com/v1alpha1;ScheduledResource"` } func NewConfig() *Config { diff --git a/pkg/common/scheduler.go b/pkg/common/scheduler.go index 4a806c0..be5a5df 100644 --- a/pkg/common/scheduler.go +++ b/pkg/common/scheduler.go @@ -30,7 +30,7 @@ func NewScheduler(config *Config, client client.Client) *Scheduler { } func (s *Scheduler) CreateOrUpdateCreationJob(date time.Time, - task func(resource v1alpha1.ScheduledResource) error, resource v1alpha1.ScheduledResource, + task func(resource v1alpha1.ScheduledResource) error, resource client.Object, ) error { tag := fmt.Sprintf("%v-create", resource.GetUID()) From 99e54f0e0706b01f51ddbc3ff66f685a0dfcdee4 Mon Sep 17 00:00:00 2001 From: Yunus Sandikci Date: Thu, 21 Dec 2023 13:53:21 +0300 Subject: [PATCH 08/12] . --- go.mod | 53 ++--- go.sum | 201 ++++++------------ pkg/apis/v1alpha1/scheduled_resource_types.go | 2 +- pkg/common/scheduler.go | 42 +--- pkg/controllers/expiration.go | 23 +- pkg/controllers/scheduled_resource.go | 54 +++-- 6 files changed, 140 insertions(+), 235 deletions(-) diff --git a/go.mod b/go.mod index 1f3d4d1..959c585 100644 --- a/go.mod +++ b/go.mod @@ -4,24 +4,24 @@ go 1.21 require ( github.com/caarlos0/env/v9 v9.0.0 - github.com/go-co-op/gocron v1.32.1 - github.com/go-echarts/go-echarts/v2 v2.2.7 + github.com/go-co-op/gocron v1.37.0 + github.com/go-echarts/go-echarts/v2 v2.3.2 github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 - github.com/prometheus/client_golang v1.16.0 - k8s.io/api v0.28.0 - k8s.io/apimachinery v0.28.0 - k8s.io/client-go v0.28.0 - sigs.k8s.io/controller-runtime v0.16.0 + github.com/prometheus/client_golang v1.17.0 + k8s.io/api v0.29.0 + k8s.io/apimachinery v0.29.0 + k8s.io/client-go v0.29.0 + sigs.k8s.io/controller-runtime v0.16.3 ) require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/emicklei/go-restful/v3 v3.9.0 // indirect + github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/zapr v1.2.4 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect @@ -30,9 +30,9 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/gnostic-models v0.6.8 // indirect - github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/uuid v1.5.0 // indirect github.com/imdario/mergo v0.3.6 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -42,33 +42,34 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.10.1 // indirect + github.com/prometheus/procfs v0.11.1 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect github.com/spf13/pflag v1.0.5 // indirect go.uber.org/atomic v1.10.0 // indirect + go.uber.org/goleak v1.3.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.25.0 // indirect - golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect - golang.org/x/net v0.13.0 // indirect - golang.org/x/oauth2 v0.8.0 // indirect - golang.org/x/sys v0.11.0 // indirect - golang.org/x/term v0.10.0 // indirect - golang.org/x/text v0.11.0 // indirect + golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/oauth2 v0.10.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/term v0.13.0 // indirect + golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.3.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.30.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.28.0 // indirect - k8s.io/component-base v0.28.0 // indirect - k8s.io/klog/v2 v2.100.1 // indirect - k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect - k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect + k8s.io/apiextensions-apiserver v0.28.3 // indirect + k8s.io/component-base v0.28.3 // indirect + k8s.io/klog/v2 v2.110.1 // indirect + k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect + k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index e4754d1..690b329 100644 --- a/go.sum +++ b/go.sum @@ -1,49 +1,32 @@ -github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= -github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= -github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df h1:7RFfzj4SSt6nnvCPbCqijJi1nWCd+TqAT3bYCStRC18= -github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= -github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/caarlos0/env/v9 v9.0.0 h1:SI6JNsOA+y5gj9njpgybykATIylrRMklbs5ch6wO6pc= github.com/caarlos0/env/v9 v9.0.0/go.mod h1:ye5mlCVMYh6tZ+vCgrs/B95sj88cg5Tlnc0XIzgZ020= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= -github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= -github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= -github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= +github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= -github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= -github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/go-co-op/gocron v1.32.1 h1:h+StA6Qzlv+ImlCaLfA26rLN9eS/l4sO7oWmPUbRVIY= -github.com/go-co-op/gocron v1.32.1/go.mod h1:UGz2oYvVS6PsqlwuOdo5L1Djsg/cQjxJ6T5ntkhp9Bg= -github.com/go-echarts/go-echarts/v2 v2.2.7 h1:mtFAuoqQ7McdlKrJ0gLexwxMPT7yoscDDhULNwPOxBk= -github.com/go-echarts/go-echarts/v2 v2.2.7/go.mod h1:VEeyPT5Odx/UHeuxtIAHGu2+87MWGA5OBaZ120NFi/w= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-co-op/gocron v1.37.0 h1:ZYDJGtQ4OMhTLKOKMIch+/CY70Brbb1dGdooLEhh7b0= +github.com/go-co-op/gocron v1.37.0/go.mod h1:3L/n6BkO7ABj+TrfSVXLRzsP26zmikL4ISkLQ0O8iNY= +github.com/go-co-op/gocron/v2 v2.1.0/go.mod h1:yuQ4a9rIMpkdBVU+Rd5EyuEKaFjl/c7ykupXHnXB6MU= +github.com/go-echarts/go-echarts/v2 v2.3.2 h1:imRxqF5sLtEPBsv5HGwz9KklNuwCo0fTITZ31mrgfzo= +github.com/go-echarts/go-echarts/v2 v2.3.2/go.mod h1:56YlvzhW/a+du15f3S2qUGNDfKnFOeJSThBIrVFHDtI= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= @@ -63,29 +46,22 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/cel-go v0.16.0 h1:DG9YQ8nFCFXAs/FDDwBxmL1tpKNrdlGUM9U3537bX/Y= -github.com/google/cel-go v0.16.0/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= +github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= -github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= @@ -113,10 +89,10 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= -github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= -github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= -github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= +github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= +github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= +github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -125,26 +101,22 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= +github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= -github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -153,44 +125,19 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -go.etcd.io/etcd/api/v3 v3.5.9 h1:4wSsluwyTbGGmyjJktOf3wFQoTBIURXHnq9n/G/JQHs= -go.etcd.io/etcd/api/v3 v3.5.9/go.mod h1:uyAal843mC8uUVSLWz6eHa/d971iDGnCRpmKd2Z+X8k= -go.etcd.io/etcd/client/pkg/v3 v3.5.9 h1:oidDC4+YEuSIQbsR94rY9gur91UPL6DnxDCIYd2IGsE= -go.etcd.io/etcd/client/pkg/v3 v3.5.9/go.mod h1:y+CzeSmkMpWN2Jyu1npecjB9BBnABxGM4pN8cGuJeL4= -go.etcd.io/etcd/client/v3 v3.5.9 h1:r5xghnU7CwbUxD/fbUtRyJGaYNfDun8sp/gTr1hew6E= -go.etcd.io/etcd/client/v3 v3.5.9/go.mod h1:i/Eo5LrZ5IKqpbtpPDuaUnDOUv471oDg8cjQaUr2MbA= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.35.0 h1:xFSRQBbXF6VvYRf2lqMJXxoB72XI1K/azav8TekHHSw= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.35.0/go.mod h1:h8TWwRAhQpOd0aM5nYsRD8+flnkj+526GEIVlarH7eY= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.1 h1:sxoY9kG1s1WpSYNyzm24rlwH4lnRYFXUVVBmKMBfRgw= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.1/go.mod h1:9NiG9I2aHTKkcxqCILhjtyNA1QEiCjdBACv4IvrFQ+c= -go.opentelemetry.io/otel v1.10.0 h1:Y7DTJMR6zs1xkS/upamJYk0SxxN4C9AqRd77jmZnyY4= -go.opentelemetry.io/otel v1.10.0/go.mod h1:NbvWjCthWHKBEUMpf0/v8ZRZlni86PpGFEMA9pnQSnQ= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0 h1:TaB+1rQhddO1sF71MpZOZAuSPW1klK2M8XxfrBMfK7Y= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0/go.mod h1:78XhIg8Ht9vR4tbLNUhXsiOnE2HOuSeKAiAcoVQEpOY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0 h1:pDDYmo0QadUPal5fwXoY1pmMpFcdyhXOmL5drCrI3vU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0/go.mod h1:Krqnjl22jUJ0HgMzw5eveuCvFDXY4nSYb4F8t5gdrag= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0 h1:KtiUEhQmj/Pa874bVYKGNVdq8NPKiacPbaRRtgXi+t4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0/go.mod h1:OfUCyyIiDvNXHWpcWgbF+MWvqPZiNa3YDEnivcnYsV0= -go.opentelemetry.io/otel/metric v0.31.0 h1:6SiklT+gfWAwWUR0meEMxQBtihpiEs4c+vL9spDTqUs= -go.opentelemetry.io/otel/metric v0.31.0/go.mod h1:ohmwj9KTSIeBnDBm/ZwH2PSZxZzoOaG2xZeekTRzL5A= -go.opentelemetry.io/otel/sdk v1.10.0 h1:jZ6K7sVn04kk/3DNUdJ4mqRlGDiXAVuIG+MMENpTNdY= -go.opentelemetry.io/otel/sdk v1.10.0/go.mod h1:vO06iKzD5baltJz1zarxMCNHFpUlUiOy4s65ECtn6kE= -go.opentelemetry.io/otel/trace v1.10.0 h1:npQMbR8o7mum8uF95yFbOEJffhs1sbCOfDh8zAJiH5E= -go.opentelemetry.io/otel/trace v1.10.0/go.mod h1:Sij3YYczqAdz+EhmGhE6TpTxUO5/F/AzrK+kxfGqySM= -go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= -go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= -go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= @@ -200,10 +147,8 @@ go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= -golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb h1:c0vyKkb6yr3KR7jEfJaOSv4lG7xPkbN6r52aJz1d8a8= +golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -215,17 +160,15 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY= -golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= -golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= -golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= +golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= -golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -234,16 +177,16 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= -golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= +golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -252,8 +195,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM= -golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM= +golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -262,18 +205,10 @@ gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54 h1:9NWlQfY2ePejTmfwUH1OWwmznFa+0kKcHGPDvcPza9M= -google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= -google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9 h1:m8v1xLLLzMe1m5P+gCTF8nJB9epwZQUBERm20Oy1poQ= -google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 h1:0nDDozoAU19Qb2HwhXadU8OcsiO/09cnTqhUtq2MEOM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= -google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag= -google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= @@ -281,41 +216,33 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= -gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.28.0 h1:3j3VPWmN9tTDI68NETBWlDiA9qOiGJ7sdKeufehBYsM= -k8s.io/api v0.28.0/go.mod h1:0l8NZJzB0i/etuWnIXcwfIv+xnDOhL3lLW919AWYDuY= -k8s.io/apiextensions-apiserver v0.28.0 h1:CszgmBL8CizEnj4sj7/PtLGey6Na3YgWyGCPONv7E9E= -k8s.io/apiextensions-apiserver v0.28.0/go.mod h1:uRdYiwIuu0SyqJKriKmqEN2jThIJPhVmOWETm8ud1VE= -k8s.io/apimachinery v0.28.0 h1:ScHS2AG16UlYWk63r46oU3D5y54T53cVI5mMJwwqFNA= -k8s.io/apimachinery v0.28.0/go.mod h1:X0xh/chESs2hP9koe+SdIAcXWcQ+RM5hy0ZynB+yEvw= -k8s.io/apiserver v0.28.0 h1:wVh7bK6Xj7hq+5ntInysTeQRAOqqFoKGUOW2yj8DXrY= -k8s.io/apiserver v0.28.0/go.mod h1:MvLmtxhQ0Tb1SZk4hfJBjs8iqr5nhYeaFSaoEcz7Lk4= -k8s.io/client-go v0.28.0 h1:ebcPRDZsCjpj62+cMk1eGNX1QkMdRmQ6lmz5BLoFWeM= -k8s.io/client-go v0.28.0/go.mod h1:0Asy9Xt3U98RypWJmU1ZrRAGKhP6NqDPmptlAzK2kMc= -k8s.io/component-base v0.28.0 h1:HQKy1enJrOeJlTlN4a6dU09wtmXaUvThC0irImfqyxI= -k8s.io/component-base v0.28.0/go.mod h1:Yyf3+ZypLfMydVzuLBqJ5V7Kx6WwDr/5cN+dFjw1FNk= -k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= -k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kms v0.28.0 h1:BwJhU9qPcJhHLUcQjtelOSjYti+1/caJLr+4jHbKzTA= -k8s.io/kms v0.28.0/go.mod h1:CNU792ls92v2Ye7Vn1jn+xLqYtUSezDZNVu6PLbJyrU= -k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ= -k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= -k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk= -k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2 h1:trsWhjU5jZrx6UvFu4WzQDrN7Pga4a7Qg+zcfcj64PA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2/go.mod h1:+qG7ISXqCDVVcyO8hLn12AKVYYUjM7ftlqsqmrhMZE0= -sigs.k8s.io/controller-runtime v0.16.0 h1:5koYaaRVBHDr0LZAJjO5dWzUjMsh6cwa7q1Mmusrdvk= -sigs.k8s.io/controller-runtime v0.16.0/go.mod h1:77DnuwA8+J7AO0njzv3wbNlMOnGuLrwFr8JPNwx3J7g= +k8s.io/api v0.29.0 h1:NiCdQMY1QOp1H8lfRyeEf8eOwV6+0xA6XEE44ohDX2A= +k8s.io/api v0.29.0/go.mod h1:sdVmXoz2Bo/cb77Pxi71IPTSErEW32xa4aXwKH7gfBA= +k8s.io/apiextensions-apiserver v0.28.3 h1:Od7DEnhXHnHPZG+W9I97/fSQkVpVPQx2diy+2EtmY08= +k8s.io/apiextensions-apiserver v0.28.3/go.mod h1:NE1XJZ4On0hS11aWWJUTNkmVB03j9LM7gJSisbRt8Lc= +k8s.io/apimachinery v0.29.0 h1:+ACVktwyicPz0oc6MTMLwa2Pw3ouLAfAon1wPLtG48o= +k8s.io/apimachinery v0.29.0/go.mod h1:eVBxQ/cwiJxH58eK/jd/vAk4mrxmVlnpBH5J2GbMeis= +k8s.io/client-go v0.29.0 h1:KmlDtFcrdUzOYrBhXHgKw5ycWzc3ryPX5mQe0SkG3y8= +k8s.io/client-go v0.29.0/go.mod h1:yLkXH4HKMAywcrD82KMSmfYg2DlE8mepPR4JGSo5n38= +k8s.io/component-base v0.28.3 h1:rDy68eHKxq/80RiMb2Ld/tbH8uAE75JdCqJyi6lXMzI= +k8s.io/component-base v0.28.3/go.mod h1:fDJ6vpVNSk6cRo5wmDa6eKIG7UlIQkaFmZN2fYgIUD8= +k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= +k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= +k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= +k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/controller-runtime v0.16.3 h1:2TuvuokmfXvDUamSx1SuAOO3eTyye+47mJCigwG62c4= +sigs.k8s.io/controller-runtime v0.16.3/go.mod h1:j7bialYoSn142nv9sCOJmQgDXQXxnroFU4VnX/brVJ0= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/pkg/apis/v1alpha1/scheduled_resource_types.go b/pkg/apis/v1alpha1/scheduled_resource_types.go index 2d50861..780db10 100644 --- a/pkg/apis/v1alpha1/scheduled_resource_types.go +++ b/pkg/apis/v1alpha1/scheduled_resource_types.go @@ -58,7 +58,7 @@ func (in *ScheduledResource) IsBeingDeleted() bool { return in.DeletionTimestamp != nil } -func (in *ScheduledResource) ToUnstructured() (*unstructured.Unstructured, error) { +func (in *ScheduledResource) GetContent() (*unstructured.Unstructured, error) { object, _, decodeErr := yaml.NewDecodingSerializer(unstructured.UnstructuredJSONScheme). Decode([]byte(in.Spec.Content), nil, nil) if decodeErr != nil { diff --git a/pkg/common/scheduler.go b/pkg/common/scheduler.go index be5a5df..d64822d 100644 --- a/pkg/common/scheduler.go +++ b/pkg/common/scheduler.go @@ -1,12 +1,10 @@ package common import ( - "fmt" "time" - "github.com/NCCloud/mayfly/pkg/apis/v1alpha1" - "github.com/go-co-op/gocron" + "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -29,32 +27,7 @@ func NewScheduler(config *Config, client client.Client) *Scheduler { return scheduler } -func (s *Scheduler) CreateOrUpdateCreationJob(date time.Time, - task func(resource v1alpha1.ScheduledResource) error, resource client.Object, -) error { - tag := fmt.Sprintf("%v-create", resource.GetUID()) - - if jobs, _ := s.scheduler.FindJobsByTag(tag); len(jobs) > 0 { - if jobs[0].NextRun().Equal(date) { - return nil - } - - if removeJobErr := s.scheduler.RemoveByTag(tag); removeJobErr != nil { - return removeJobErr - } - } - - _, jobErr := s.scheduler.StartAt(date).Every(1).LimitRunsTo(1).Tag(tag). - Do(task, resource) - - return jobErr -} - -func (s *Scheduler) CreateOrUpdateDeletionJob(date time.Time, - task func(resource client.Object) error, resource client.Object, -) error { - tag := fmt.Sprintf("%v-delete", resource.GetUID()) - +func (s *Scheduler) CreateOrUpdateTask(tag string, date time.Time, task func() error) error { if jobs, _ := s.scheduler.FindJobsByTag(tag); len(jobs) > 0 { if jobs[0].NextRun().Equal(date) { return nil @@ -65,18 +38,13 @@ func (s *Scheduler) CreateOrUpdateDeletionJob(date time.Time, } } - _, jobErr := s.scheduler.StartAt(date).Every(1).LimitRunsTo(1).Tag(tag). - Do(task, resource) + _, jobErr := s.scheduler.StartAt(date).Every(1).LimitRunsTo(1).Tag(tag).Do(task) return jobErr } -func (s *Scheduler) DeleteCreationJob(resource client.Object) error { - return s.scheduler.RemoveByTag(fmt.Sprintf("%v-create", resource.GetUID())) -} - -func (s *Scheduler) DeleteDeletionJob(resource client.Object) error { - return s.scheduler.RemoveByTag(fmt.Sprintf("%v-delete", resource.GetUID())) +func (s *Scheduler) DeleteTask(tag string) error { + return s.scheduler.RemoveByTag(tag) } func (s *Scheduler) startMonitoring() { diff --git a/pkg/controllers/expiration.go b/pkg/controllers/expiration.go index a7732be..4e514b5 100644 --- a/pkg/controllers/expiration.go +++ b/pkg/controllers/expiration.go @@ -2,6 +2,7 @@ package controllers import ( "context" + "fmt" "github.com/NCCloud/mayfly/pkg/common" @@ -35,13 +36,15 @@ func (r *ExpirationController) Reconcile(ctx context.Context, req ctrl.Request) var ( logger = log.FromContext(ctx) resource = common.NewResourceInstance(r.apiVersionKind) + tag = fmt.Sprintf("%s-%s/delete", req.Name, req.Namespace) ) logger.Info("Reconciliation started.") + defer logger.Info("Reconciliation finished.") if getErr := r.client.Get(ctx, req.NamespacedName, resource); getErr != nil { if errors.IsNotFound(getErr) { - _ = r.scheduler.DeleteDeletionJob(resource) + _ = r.scheduler.DeleteTask(tag) } return ctrl.Result{}, client.IgnoreNotFound(getErr) @@ -55,21 +58,19 @@ func (r *ExpirationController) Reconcile(ctx context.Context, req ctrl.Request) } if hasExpired { - logger.Info("Resource already expired. Removing") + logger.Info("Resource already expired will be removed.") - _ = r.client.Delete(ctx, resource) - _ = r.scheduler.DeleteDeletionJob(resource) + _ = r.scheduler.DeleteTask(tag) - return ctrl.Result{}, nil + return ctrl.Result{}, client.IgnoreNotFound(r.client.Delete(ctx, resource)) } - if createOrUpdateErr := r.scheduler.CreateOrUpdateDeletionJob(expirationDate, - func(resource client.Object) error { - return r.client.Delete(context.Background(), resource) - }, resource); createOrUpdateErr != nil { - logger.Error(createOrUpdateErr, "Error while starting job.") + if createOrUpdateTaskErr := r.scheduler.CreateOrUpdateTask(tag, expirationDate, func() error { + return r.client.Delete(context.Background(), resource) + }); createOrUpdateTaskErr != nil { + logger.Error(createOrUpdateTaskErr, "Error while creating or updating task.") - return ctrl.Result{}, createOrUpdateErr + return ctrl.Result{}, createOrUpdateTaskErr } return ctrl.Result{}, nil diff --git a/pkg/controllers/scheduled_resource.go b/pkg/controllers/scheduled_resource.go index 77e8752..5bfa495 100644 --- a/pkg/controllers/scheduled_resource.go +++ b/pkg/controllers/scheduled_resource.go @@ -36,60 +36,68 @@ func (r *ScheduledResourceController) Reconcile(ctx context.Context, req ctrl.Re var ( logger = log.FromContext(ctx) scheduledResource = &v1alpha1.ScheduledResource{} + tag = fmt.Sprintf("%s-%s/delete", req.Name, req.Namespace) ) + logger.Info("Reconciliation started.") + defer logger.Info("Reconciliation finished.") + if getErr := r.client.Get(ctx, req.NamespacedName, scheduledResource); getErr != nil { if errors.IsNotFound(getErr) { - _ = r.scheduler.DeleteCreationJob(scheduledResource) + _ = r.scheduler.DeleteTask(tag) } return ctrl.Result{}, client.IgnoreNotFound(getErr) } - logger.Info("Reconciliation started.") - if scheduledResource.Status.Condition == v1alpha1.ConditionCreated { return ctrl.Result{}, nil } duration, parseDurationErr := time.ParseDuration(scheduledResource.Spec.In) if parseDurationErr != nil { + logger.Error(parseDurationErr, "Error while parsing duration.") + return ctrl.Result{}, parseDurationErr } - if createOrUpdateErr := r.scheduler.CreateOrUpdateCreationJob(scheduledResource.CreationTimestamp.Add(duration), - func(resource v1alpha1.ScheduledResource) error { - unstructured, toUnstructuredErr := resource.ToUnstructured() - if toUnstructuredErr != nil { - return toUnstructuredErr + if createOrUpdateTaskErr := r.scheduler.CreateOrUpdateTask(tag, scheduledResource.CreationTimestamp.Add(duration), + func() error { + content, contentErr := scheduledResource.GetContent() + if contentErr != nil { + logger.Error(contentErr, "Error while parsing content.") + + return contentErr } - if getErr := r.client.Get(context.Background(), - client.ObjectKeyFromObject(&resource), &resource); getErr != nil { + if getErr := r.client.Get(context.Background(), client. + ObjectKeyFromObject(scheduledResource), scheduledResource); client.IgnoreNotFound(getErr) != nil { + logger.Error(contentErr, "Error while getting resource.") + return getErr } if createErr := r.client.Create(context.Background(), - unstructured); client.IgnoreAlreadyExists(createErr) != nil { - resource.Status.Condition = v1alpha1.ConditionFailed + content); client.IgnoreAlreadyExists(createErr) != nil { + logger.Error(contentErr, "An error occurred while creating resource.") + + scheduledResource.Status.Condition = v1alpha1.ConditionFailed - return errors2.Join(createErr, r.client.Status().Update(context.Background(), &resource)) + return errors2.Join(createErr, r.client.Status().Update(context.Background(), scheduledResource)) } - logger.Info(fmt.Sprintf("%s/%s created.", resource.Name, resource.Namespace)) + logger.Info(fmt.Sprintf("%s created.", tag)) - if removeErr := r.scheduler.DeleteCreationJob(&resource); removeErr != nil { - return removeErr - } + _ = r.scheduler.DeleteTask(tag) - resource.Status.Condition = v1alpha1.ConditionCreated + scheduledResource.Status.Condition = v1alpha1.ConditionCreated - return r.client.Status().Update(context.Background(), &resource) - }, *scheduledResource); createOrUpdateErr != nil { - return ctrl.Result{}, createOrUpdateErr - } + return r.client.Status().Update(context.Background(), scheduledResource) + }); createOrUpdateTaskErr != nil { + logger.Error(createOrUpdateTaskErr, "Error while creating or updating task.") - logger.Info("Reconciliation finished.") + return ctrl.Result{}, createOrUpdateTaskErr + } scheduledResource.Status.Condition = v1alpha1.ConditionScheduled From d59a75717a25d70fa51c2798d4f3cb64873bd26c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Sand=C4=B1kc=C4=B1?= Date: Thu, 21 Dec 2023 22:32:48 +0300 Subject: [PATCH 09/12] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 1e75d63..11fb3cc 100644 --- a/README.md +++ b/README.md @@ -3,19 +3,19 @@ logo -> Mayfly is a Kubernetes operator that enables you to create temporary resources on the cluster that will expire after a certain period of time. +> Mayfly is a Kubernetes operator that enables you to have time-based resources. They creates or deletes on the specified time. ## 📖 General Information ### 📄 Summary -The Mayfly Operator allows you to have your resources on your cluster for a temporary time. -It deletes those resources from the cluster, according to the Mayfly expiration annotation that you set to specify how long the resource should remain active. This can be used to create temporary resources, temporary accesses, or simply to keep your cluster organized and tidy. +The Mayfly Operator allows you to expire the resources on your cluster by the given expiration or mayfly create the resources at the time you specified. +It deletes those resources from the cluster, according to the Mayfly expiration annotation that you set to specify how long the resource should remain active. This can be used to create temporary resources, temporary accesses, or simply to keep your cluster organized and tidy. Also, It creates the resources you specific at the given time by creating `ScheduleResource` custom resource definitions. You can also merge these two features together, just to have some resource created in the future and only for a specific amount of time. ### 🛠 Configuration Mayfly is an easy-to-use and configurable project that uses resource watches and schedulers to delete your resources at the appropriate time. It is simple to set up and customize. -To specify which resources should be monitored and cleaned up, you can set the `RESOURCES` environment variable to a comma-separated list of `{ApiVersion};{Kind}` as text. This allows you to customize which resources are targeted for cleanup. +To specify which resources should be monitored and cleaned up, you can set the `RESOURCES` environment variable to a comma-separated list of `{ApiVersion};{Kind}` as text. This allows you to customize which resources are targeted for cleanup with expiration annotations. Example: ``` @@ -48,7 +48,7 @@ spec: ### Scheduled Resource Creation -The ScheduledResource CRD allows you to schedule the creation of an object in the future. This can be combined with the expire annotation, enabling Mayfly to create and remove certain objects for a temporary period in the future. +The `ScheduledResource` CRD allows you to schedule the creation of an object in the future. This can be combined with the expire annotation, enabling Mayfly to create and remove certain objects for a temporary period in the future. Example: ``` From 7a888f4734081ec502d4cde18fe009cf7c764817 Mon Sep 17 00:00:00 2001 From: Yunus Sandikci Date: Mon, 15 Jan 2024 12:58:57 +0300 Subject: [PATCH 10/12] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 11fb3cc..7fbd592 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,9 @@ ### 📄 Summary -The Mayfly Operator allows you to expire the resources on your cluster by the given expiration or mayfly create the resources at the time you specified. -It deletes those resources from the cluster, according to the Mayfly expiration annotation that you set to specify how long the resource should remain active. This can be used to create temporary resources, temporary accesses, or simply to keep your cluster organized and tidy. Also, It creates the resources you specific at the given time by creating `ScheduleResource` custom resource definitions. You can also merge these two features together, just to have some resource created in the future and only for a specific amount of time. +The Mayfly Operator allows you to have your resources on your cluster for a temporary time by the given expiration or mayfly create the resources at the time you specified. +It deletes those resources from the cluster, according to the Mayfly expiration annotation that you set to specify how long the resource should remain active. This can be used to create temporary resources, temporary accesses, or simply to keep your cluster organized and tidy. +Also, It creates the resources you specify at the given time by using `ScheduleResource` custom resource definition. You can also merge these two features together, just to have some resource created in the future and only for a specific amount of time. ### 🛠 Configuration From de70de2fa62bef45452ac63a0644c865e3bb7da5 Mon Sep 17 00:00:00 2001 From: Yunus Sandikci Date: Mon, 15 Jan 2024 13:00:31 +0300 Subject: [PATCH 11/12] . --- .../crds/cloud.namecheap.com_scheduledresources.yaml | 3 +++ example.yaml | 10 ---------- pkg/apis/v1alpha1/scheduled_resource_types.go | 1 + 3 files changed, 4 insertions(+), 10 deletions(-) delete mode 100644 example.yaml diff --git a/deploy/crds/cloud.namecheap.com_scheduledresources.yaml b/deploy/crds/cloud.namecheap.com_scheduledresources.yaml index d6e237a..b619053 100644 --- a/deploy/crds/cloud.namecheap.com_scheduledresources.yaml +++ b/deploy/crds/cloud.namecheap.com_scheduledresources.yaml @@ -15,6 +15,9 @@ spec: scope: Namespaced versions: - additionalPrinterColumns: + - jsonPath: .spec.in + name: In + type: date - jsonPath: .metadata.creationTimestamp name: Age type: date diff --git a/example.yaml b/example.yaml deleted file mode 100644 index 7d21f86..0000000 --- a/example.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: website-1-temp - namespace: default - annotations: - mayfly.cloud.namecheap.com/expire: 10s -data: - mysql-user-password: cUIzN3Y5cmo4bmN5TmI2NVVWMDQxMktZ -type: Opaque diff --git a/pkg/apis/v1alpha1/scheduled_resource_types.go b/pkg/apis/v1alpha1/scheduled_resource_types.go index 780db10..83faf44 100644 --- a/pkg/apis/v1alpha1/scheduled_resource_types.go +++ b/pkg/apis/v1alpha1/scheduled_resource_types.go @@ -27,6 +27,7 @@ func init() { //+kubebuilder:object:root=true //+kubebuilder:subresource:status +//+kubebuilder:printcolumn:name="In",type=date,JSONPath=".spec.in" //+kubebuilder:printcolumn:name="Age",type=date,JSONPath=".metadata.creationTimestamp" type ScheduledResource struct { From 1683e8b7cba75e516d974ad87926b6965d78f635 Mon Sep 17 00:00:00 2001 From: Yunus Sandikci Date: Mon, 15 Jan 2024 13:28:17 +0300 Subject: [PATCH 12/12] . --- .../cloud.namecheap.com_scheduledresources.yaml | 5 ++++- docs/api.md | 10 +++++----- examples/{example.yaml => combination.yaml} | 10 +++++----- examples/expiration.yaml | 9 +++++++++ examples/scheduled_resource.yaml | 14 ++++++++++++++ pkg/apis/v1alpha1/scheduled_resource_types.go | 11 ++++++----- pkg/apis/v1alpha1/zz_generated.deepcopy.go | 16 ++++++++-------- pkg/controllers/expiration.go | 7 ++++--- pkg/controllers/scheduled_resource.go | 4 +++- 9 files changed, 58 insertions(+), 28 deletions(-) rename examples/{example.yaml => combination.yaml} (60%) create mode 100644 examples/expiration.yaml create mode 100644 examples/scheduled_resource.yaml diff --git a/deploy/crds/cloud.namecheap.com_scheduledresources.yaml b/deploy/crds/cloud.namecheap.com_scheduledresources.yaml index b619053..e909dbb 100644 --- a/deploy/crds/cloud.namecheap.com_scheduledresources.yaml +++ b/deploy/crds/cloud.namecheap.com_scheduledresources.yaml @@ -17,10 +17,13 @@ spec: - additionalPrinterColumns: - jsonPath: .spec.in name: In - type: date + type: string - jsonPath: .metadata.creationTimestamp name: Age type: date + - jsonPath: .status.condition + name: Condition + type: string name: v1alpha1 schema: openAPIV3Schema: diff --git a/docs/api.md b/docs/api.md index d8e0a7e..c3fb1c5 100644 --- a/docs/api.md +++ b/docs/api.md @@ -20,7 +20,7 @@ _Underlying type:_ _string_ _Appears in:_ -- [ScheduledStatus](#scheduledstatus) +- [ScheduledResourceStatus](#scheduledresourcestatus) @@ -41,11 +41,11 @@ _Appears in:_ | `kind` _string_ | 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 | | `apiVersion` _string_ | 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 | | `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | -| `spec` _[ScheduledSpec](#scheduledspec)_ | | -| `status` _[ScheduledStatus](#scheduledstatus)_ | | +| `spec` _[ScheduledResourceSpec](#scheduledresourcespec)_ | | +| `status` _[ScheduledResourceStatus](#scheduledresourcestatus)_ | | -#### ScheduledSpec +#### ScheduledResourceSpec @@ -60,7 +60,7 @@ _Appears in:_ | `content` _string_ | | -#### ScheduledStatus +#### ScheduledResourceStatus diff --git a/examples/example.yaml b/examples/combination.yaml similarity index 60% rename from examples/example.yaml rename to examples/combination.yaml index cf38b4f..da66c61 100644 --- a/examples/example.yaml +++ b/examples/combination.yaml @@ -1,18 +1,18 @@ apiVersion: cloud.namecheap.com/v1alpha1 kind: ScheduledResource metadata: - name: example + name: combination-example annotations: - mayfly.cloud.namecheap.com/expire: 30s + mayfly.cloud.namecheap.com/expire: 10s spec: - in: "15s" + in: "5s" content: | apiVersion: v1 kind: Secret metadata: - name: example + name: combination-example namespace: default annotations: - mayfly.cloud.namecheap.com/expire: 15s + mayfly.cloud.namecheap.com/expire: 10s data: .secret-file: dmFsdWUtMg0KDQo= \ No newline at end of file diff --git a/examples/expiration.yaml b/examples/expiration.yaml new file mode 100644 index 0000000..b89a0fe --- /dev/null +++ b/examples/expiration.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Secret +metadata: + name: expiration-example + namespace: default + annotations: + mayfly.cloud.namecheap.com/expire: 10s +data: + .secret-file: dmFsdWUtMg0KDQo= \ No newline at end of file diff --git a/examples/scheduled_resource.yaml b/examples/scheduled_resource.yaml new file mode 100644 index 0000000..ce5e72b --- /dev/null +++ b/examples/scheduled_resource.yaml @@ -0,0 +1,14 @@ +apiVersion: cloud.namecheap.com/v1alpha1 +kind: ScheduledResource +metadata: + name: scheduled-resource-example +spec: + in: "5s" + content: | + apiVersion: v1 + kind: Secret + metadata: + name: scheduled-resource-example + namespace: default + data: + .secret-file: dmFsdWUtMg0KDQo= \ No newline at end of file diff --git a/pkg/apis/v1alpha1/scheduled_resource_types.go b/pkg/apis/v1alpha1/scheduled_resource_types.go index 83faf44..9cc75b4 100644 --- a/pkg/apis/v1alpha1/scheduled_resource_types.go +++ b/pkg/apis/v1alpha1/scheduled_resource_types.go @@ -27,15 +27,16 @@ func init() { //+kubebuilder:object:root=true //+kubebuilder:subresource:status -//+kubebuilder:printcolumn:name="In",type=date,JSONPath=".spec.in" +//+kubebuilder:printcolumn:name="In",type=string,JSONPath=".spec.in" //+kubebuilder:printcolumn:name="Age",type=date,JSONPath=".metadata.creationTimestamp" +//+kubebuilder:printcolumn:name="Condition",type=string,JSONPath=".status.condition" type ScheduledResource struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Spec ScheduledSpec `json:"spec,omitempty"` - Status ScheduledStatus `json:"status,omitempty"` + Spec ScheduledResourceSpec `json:"spec,omitempty"` + Status ScheduledResourceStatus `json:"status,omitempty"` } //+kubebuilder:object:root=true @@ -46,12 +47,12 @@ type ScheduledResourceList struct { Items []ScheduledResource `json:"items"` } -type ScheduledSpec struct { +type ScheduledResourceSpec struct { In string `json:"in"` Content string `json:"content"` } -type ScheduledStatus struct { +type ScheduledResourceStatus struct { Condition Condition `json:"condition"` } diff --git a/pkg/apis/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/v1alpha1/zz_generated.deepcopy.go index eee17bf..0e7fb1c 100644 --- a/pkg/apis/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/v1alpha1/zz_generated.deepcopy.go @@ -68,31 +68,31 @@ func (in *ScheduledResourceList) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ScheduledSpec) DeepCopyInto(out *ScheduledSpec) { +func (in *ScheduledResourceSpec) DeepCopyInto(out *ScheduledResourceSpec) { *out = *in } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScheduledSpec. -func (in *ScheduledSpec) DeepCopy() *ScheduledSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScheduledResourceSpec. +func (in *ScheduledResourceSpec) DeepCopy() *ScheduledResourceSpec { if in == nil { return nil } - out := new(ScheduledSpec) + out := new(ScheduledResourceSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ScheduledStatus) DeepCopyInto(out *ScheduledStatus) { +func (in *ScheduledResourceStatus) DeepCopyInto(out *ScheduledResourceStatus) { *out = *in } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScheduledStatus. -func (in *ScheduledStatus) DeepCopy() *ScheduledStatus { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScheduledResourceStatus. +func (in *ScheduledResourceStatus) DeepCopy() *ScheduledResourceStatus { if in == nil { return nil } - out := new(ScheduledStatus) + out := new(ScheduledResourceStatus) in.DeepCopyInto(out) return out } diff --git a/pkg/controllers/expiration.go b/pkg/controllers/expiration.go index 4e514b5..4c41923 100644 --- a/pkg/controllers/expiration.go +++ b/pkg/controllers/expiration.go @@ -34,9 +34,10 @@ func NewExpirationController(config *common.Config, client client.Client, func (r *ExpirationController) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { var ( - logger = log.FromContext(ctx) - resource = common.NewResourceInstance(r.apiVersionKind) - tag = fmt.Sprintf("%s-%s/delete", req.Name, req.Namespace) + logger = log.FromContext(ctx) + resource = common.NewResourceInstance(r.apiVersionKind) + apiVersion, kind = resource.GroupVersionKind().ToAPIVersionAndKind() + tag = fmt.Sprintf("%s/%s/%s/%s/delete", apiVersion, kind, req.Name, req.Namespace) ) logger.Info("Reconciliation started.") diff --git a/pkg/controllers/scheduled_resource.go b/pkg/controllers/scheduled_resource.go index 5bfa495..5b025f2 100644 --- a/pkg/controllers/scheduled_resource.go +++ b/pkg/controllers/scheduled_resource.go @@ -36,9 +36,11 @@ func (r *ScheduledResourceController) Reconcile(ctx context.Context, req ctrl.Re var ( logger = log.FromContext(ctx) scheduledResource = &v1alpha1.ScheduledResource{} - tag = fmt.Sprintf("%s-%s/delete", req.Name, req.Namespace) + tag = fmt.Sprintf("v1alpha1/ScheduledResource/%s/%s/create", req.Name, req.Namespace) ) + scheduledResource.GroupVersionKind().ToAPIVersionAndKind() + logger.Info("Reconciliation started.") defer logger.Info("Reconciliation finished.")