From 709ed84880f088583ce37e3aca05a2ed44c947ff Mon Sep 17 00:00:00 2001 From: LOngquan Sha Date: Mon, 27 Oct 2025 09:33:04 +0000 Subject: [PATCH 1/5] Create sonic device CRD --- pkg/apis/samplecontroller/v1alpha1/types.go | 58 ++++++++++++++++----- 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/pkg/apis/samplecontroller/v1alpha1/types.go b/pkg/apis/samplecontroller/v1alpha1/types.go index 74ffc6721..28774e9f8 100644 --- a/pkg/apis/samplecontroller/v1alpha1/types.go +++ b/pkg/apis/samplecontroller/v1alpha1/types.go @@ -23,32 +23,62 @@ import ( // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// Foo is a specification for a Foo resource -type Foo struct { +// NetworkDevice is a specification for a NetworkDevice resource +type NetworkDevice struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Spec FooSpec `json:"spec"` - Status FooStatus `json:"status"` + Spec NetworkDeviceSpec `json:"spec"` + Status NetworkDeviceStatus `json:"status"` } -// FooSpec is the spec for a Foo resource -type FooSpec struct { - DeploymentName string `json:"deploymentName"` - Replicas *int32 `json:"replicas"` +// NetworkDeviceSpec is the spec for a NetworkDevice resource +type NetworkDeviceSpec struct { + OS OSInfo `json:"os,omitempty"` } -// FooStatus is the status for a Foo resource -type FooStatus struct { - AvailableReplicas int32 `json:"availableReplicas"` +type OSInfo struct { + OSType string `json:"os-type,omitempty"` + Version string `json:"version,omitempty"` } +// NetworkDeviceStatus is the status for a NetworkDevice resource +type NetworkDeviceStatus struct { + State string `json:"state,omitempty"` + LastTransitionTime string `json:"lastTransitionTime,omitempty"` + OS OSStatus `json:"os,omitempty"` + Conditions []Condition `json:"conditions,omitempty"` + Operation OperationStatus `json:"operation,omitempty"` +} +// Condition represents a status condition +type Condition struct { + Type string `json:"type,omitempty"` + Status string `json:"status,omitempty"` + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` + Reason string `json:"reason,omitempty"` + Message string `json:"message,omitempty"` +} + +// OperationStatus describes an operation in status +type OperationStatus struct { + Name string `json:"name,omitempty"` + ID string `json:"id,omitempty"` + Status string `json:"status,omitempty"` + OperationAction OperationAction `json:"operationAction,omitempty"` +} + +// OperationAction describes the action of an operation +type OperationAction struct { + Name string `json:"name,omitempty"` + ID string `json:"id,omitempty"` + Status string `json:"status,omitempty"` +} // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// FooList is a list of Foo resources -type FooList struct { +// NetworkDeviceList is a list of NetworkDevice resources +type NetworkDeviceList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata"` - Items []Foo `json:"items"` + Items []NetworkDevice `json:"items"` } From 35241c9f527153fcc039039aa23d5e719438e231 Mon Sep 17 00:00:00 2001 From: LOngquan Sha Date: Tue, 28 Oct 2025 08:27:58 +0000 Subject: [PATCH 2/5] Create sonic device controller --- config/crd/admin.conf | 0 config/crd/device_example.yaml | 30 ++ config/crd/sonick8s.io_networkdevices.yaml | 111 ++++++ go.mod | 83 ++-- hack/update-codegen-sonic.sh | 37 ++ main.go | 10 +- pkg/apis/samplecontroller/v1alpha1/doc.go | 2 +- .../samplecontroller/v1alpha1/register.go | 2 +- pkg/apis/samplecontroller/v1alpha1/types.go | 60 +-- pkg/apis/sonic/register.go | 22 ++ pkg/apis/sonic/v1alpha1/doc.go | 21 ++ pkg/apis/sonic/v1alpha1/register.go | 54 +++ pkg/apis/sonic/v1alpha1/types.go | 88 +++++ .../sonic/v1alpha1/zz_generated.deepcopy.go | 196 ++++++++++ pkg/controller/networkdevice_controller.go | 353 ++++++++++++++++++ pkg/controller/operation.go | 62 +++ .../clientset/versioned/clientset.go | 133 +++++++ .../versioned/fake/clientset_generated.go | 112 ++++++ .../generated/clientset/versioned/fake/doc.go | 20 + .../clientset/versioned/fake/register.go | 58 +++ .../clientset/versioned/scheme/doc.go | 20 + .../clientset/versioned/scheme/register.go | 58 +++ .../typed/samplecontroller/v1alpha1/doc.go | 20 + .../samplecontroller/v1alpha1/fake/doc.go | 20 + .../v1alpha1/fake/fake_foo.go | 48 +++ .../fake/fake_samplecontroller_client.go | 40 ++ .../typed/samplecontroller/v1alpha1/foo.go | 70 ++++ .../v1alpha1/generated_expansion.go | 21 ++ .../v1alpha1/samplecontroller_client.go | 101 +++++ .../versioned/typed/sonic/v1alpha1/doc.go | 20 + .../typed/sonic/v1alpha1/fake/doc.go | 20 + .../sonic/v1alpha1/fake/fake_networkdevice.go | 52 +++ .../sonic/v1alpha1/fake/fake_sonic_client.go | 40 ++ .../sonic/v1alpha1/generated_expansion.go | 21 ++ .../typed/sonic/v1alpha1/networkdevice.go | 70 ++++ .../typed/sonic/v1alpha1/sonic_client.go | 101 +++++ .../informers/externalversions/factory.go | 269 +++++++++++++ .../informers/externalversions/generic.go | 67 ++++ .../internalinterfaces/factory_interfaces.go | 40 ++ .../samplecontroller/interface.go | 46 +++ .../samplecontroller/v1alpha1/foo.go | 102 +++++ .../samplecontroller/v1alpha1/interface.go | 45 +++ .../externalversions/sonic/interface.go | 46 +++ .../sonic/v1alpha1/interface.go | 45 +++ .../sonic/v1alpha1/networkdevice.go | 102 +++++ .../v1alpha1/expansion_generated.go | 27 ++ .../listers/samplecontroller/v1alpha1/foo.go | 70 ++++ .../sonic/v1alpha1/expansion_generated.go | 27 ++ .../listers/sonic/v1alpha1/networkdevice.go | 70 ++++ 49 files changed, 3037 insertions(+), 95 deletions(-) create mode 100644 config/crd/admin.conf create mode 100644 config/crd/device_example.yaml create mode 100644 config/crd/sonick8s.io_networkdevices.yaml create mode 100755 hack/update-codegen-sonic.sh create mode 100644 pkg/apis/sonic/register.go create mode 100644 pkg/apis/sonic/v1alpha1/doc.go create mode 100644 pkg/apis/sonic/v1alpha1/register.go create mode 100644 pkg/apis/sonic/v1alpha1/types.go create mode 100644 pkg/apis/sonic/v1alpha1/zz_generated.deepcopy.go create mode 100644 pkg/controller/networkdevice_controller.go create mode 100644 pkg/controller/operation.go create mode 100644 pkg/sonick8s/generated/clientset/versioned/clientset.go create mode 100644 pkg/sonick8s/generated/clientset/versioned/fake/clientset_generated.go create mode 100644 pkg/sonick8s/generated/clientset/versioned/fake/doc.go create mode 100644 pkg/sonick8s/generated/clientset/versioned/fake/register.go create mode 100644 pkg/sonick8s/generated/clientset/versioned/scheme/doc.go create mode 100644 pkg/sonick8s/generated/clientset/versioned/scheme/register.go create mode 100644 pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/doc.go create mode 100644 pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/fake/doc.go create mode 100644 pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/fake/fake_foo.go create mode 100644 pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/fake/fake_samplecontroller_client.go create mode 100644 pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/foo.go create mode 100644 pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/generated_expansion.go create mode 100644 pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/samplecontroller_client.go create mode 100644 pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/doc.go create mode 100644 pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/fake/doc.go create mode 100644 pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/fake/fake_networkdevice.go create mode 100644 pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/fake/fake_sonic_client.go create mode 100644 pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/generated_expansion.go create mode 100644 pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/networkdevice.go create mode 100644 pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/sonic_client.go create mode 100644 pkg/sonick8s/generated/informers/externalversions/factory.go create mode 100644 pkg/sonick8s/generated/informers/externalversions/generic.go create mode 100644 pkg/sonick8s/generated/informers/externalversions/internalinterfaces/factory_interfaces.go create mode 100644 pkg/sonick8s/generated/informers/externalversions/samplecontroller/interface.go create mode 100644 pkg/sonick8s/generated/informers/externalversions/samplecontroller/v1alpha1/foo.go create mode 100644 pkg/sonick8s/generated/informers/externalversions/samplecontroller/v1alpha1/interface.go create mode 100644 pkg/sonick8s/generated/informers/externalversions/sonic/interface.go create mode 100644 pkg/sonick8s/generated/informers/externalversions/sonic/v1alpha1/interface.go create mode 100644 pkg/sonick8s/generated/informers/externalversions/sonic/v1alpha1/networkdevice.go create mode 100644 pkg/sonick8s/generated/listers/samplecontroller/v1alpha1/expansion_generated.go create mode 100644 pkg/sonick8s/generated/listers/samplecontroller/v1alpha1/foo.go create mode 100644 pkg/sonick8s/generated/listers/sonic/v1alpha1/expansion_generated.go create mode 100644 pkg/sonick8s/generated/listers/sonic/v1alpha1/networkdevice.go diff --git a/config/crd/admin.conf b/config/crd/admin.conf new file mode 100644 index 000000000..e69de29bb diff --git a/config/crd/device_example.yaml b/config/crd/device_example.yaml new file mode 100644 index 000000000..ff2f7db33 --- /dev/null +++ b/config/crd/device_example.yaml @@ -0,0 +1,30 @@ +apiVersion: sonick8s.io/v1alpha1 +kind: NetworkDevice +metadata: + name: example-networkdevice + namespace: default +spec: + os: + os-type: "SONiC" + version: "202305" +status: + state: "Healthy" + lastTransitionTime: "2025-10-28T12:00:00Z" + os: + os-type: "SONiC" + version: "202305" + operation: + id: "op-123" + name: "Upgrade" + status: "Completed" + operationAction: + id: "action-1" + name: "Install" + status: "Success" + conditions: + - type: "Ready" + status: "True" + lastProbeTime: "2025-10-28T12:00:00Z" + lastTransitionTime: "2025-10-28T12:00:00Z" + reason: "AllSystemsGo" + message: "Device is ready" \ No newline at end of file diff --git a/config/crd/sonick8s.io_networkdevices.yaml b/config/crd/sonick8s.io_networkdevices.yaml new file mode 100644 index 000000000..62baf191a --- /dev/null +++ b/config/crd/sonick8s.io_networkdevices.yaml @@ -0,0 +1,111 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.19.0 + name: networkdevices.sonick8s.io +spec: + group: sonick8s.io + names: + kind: NetworkDevice + listKind: NetworkDeviceList + plural: networkdevices + singular: networkdevice + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: NetworkDevice is a specification for a NetworkDevice resource + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: NetworkDeviceSpec is the spec for a NetworkDevice resource + properties: + os: + properties: + os-type: + type: string + version: + type: string + type: object + type: object + status: + description: NetworkDeviceStatus is the status for a NetworkDevice resource + properties: + conditions: + items: + description: Condition represents a status condition + properties: + lastProbeTime: + format: date-time + type: string + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + type: object + type: array + lastTransitionTime: + type: string + operation: + description: OperationStatus describes an operation in status + properties: + id: + type: string + name: + type: string + operationAction: + description: OperationAction describes the action of an operation + properties: + id: + type: string + name: + type: string + status: + type: string + type: object + status: + type: string + type: object + os: + properties: + os-type: + type: string + version: + type: string + type: object + state: + type: string + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} diff --git a/go.mod b/go.mod index 35b04c1cc..98f3f56f8 100644 --- a/go.mod +++ b/go.mod @@ -4,56 +4,53 @@ module k8s.io/sample-controller go 1.25.0 -godebug default=go1.25 +// godebug default=go1.25 require ( + github.com/davecgh/go-spew v1.1.1 + github.com/emicklei/go-restful/v3 v3.12.2 + github.com/fxamacker/cbor/v2 v2.9.0 + github.com/go-logr/logr v1.4.3 + github.com/go-openapi/jsonpointer v0.21.0 + github.com/go-openapi/jsonreference v0.20.2 + github.com/go-openapi/swag v0.23.0 + github.com/google/gnostic-models v0.7.0 + github.com/google/go-cmp v0.7.0 + github.com/google/uuid v1.6.0 + github.com/josharian/intern v1.0.0 + github.com/json-iterator/go v1.1.12 + github.com/mailru/easyjson v0.7.7 + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd + github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 + github.com/pmezard/go-difflib v1.0.0 + github.com/spf13/pflag v1.0.9 + github.com/x448/float16 v0.8.4 + go.yaml.in/yaml/v2 v2.4.2 + go.yaml.in/yaml/v3 v3.0.4 + golang.org/x/mod v0.27.0 + golang.org/x/net v0.43.0 + golang.org/x/oauth2 v0.30.0 + golang.org/x/sync v0.16.0 + golang.org/x/sys v0.35.0 + golang.org/x/term v0.34.0 + golang.org/x/text v0.28.0 golang.org/x/time v0.9.0 + golang.org/x/tools v0.36.0 + google.golang.org/protobuf v1.36.8 + gopkg.in/evanphx/json-patch.v4 v4.13.0 + gopkg.in/inf.v0 v0.9.1 + gopkg.in/yaml.v3 v3.0.1 k8s.io/api v0.0.0-20251022232024-e681e9f64143 k8s.io/apimachinery v0.0.0-20251022231703-e79daceaa31b k8s.io/client-go v0.0.0-20251022232504-715199a180dc k8s.io/code-generator v0.0.0-20251022233416-62789f7b54ab + k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b k8s.io/klog/v2 v2.130.1 + k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 -) - -require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/emicklei/go-restful/v3 v3.12.2 // indirect - github.com/fxamacker/cbor/v2 v2.9.0 // indirect - github.com/go-logr/logr v1.4.3 // indirect - github.com/go-openapi/jsonpointer v0.21.0 // indirect - github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/go-openapi/swag v0.23.0 // indirect - github.com/google/gnostic-models v0.7.0 // indirect - github.com/google/go-cmp v0.7.0 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/josharian/intern v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/mailru/easyjson v0.7.7 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/spf13/pflag v1.0.9 // indirect - github.com/x448/float16 v0.8.4 // indirect - go.yaml.in/yaml/v2 v2.4.2 // indirect - go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/mod v0.27.0 // indirect - golang.org/x/net v0.43.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sync v0.16.0 // indirect - golang.org/x/sys v0.35.0 // indirect - golang.org/x/term v0.34.0 // indirect - golang.org/x/text v0.28.0 // indirect - golang.org/x/tools v0.36.0 // indirect - google.golang.org/protobuf v1.36.8 // indirect - gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect - gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b // indirect - k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect - sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect - sigs.k8s.io/randfill v1.0.0 // indirect - sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect - sigs.k8s.io/yaml v1.6.0 // indirect + sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 + sigs.k8s.io/randfill v1.0.0 + sigs.k8s.io/structured-merge-diff/v6 v6.3.0 + sigs.k8s.io/yaml v1.6.0 ) diff --git a/hack/update-codegen-sonic.sh b/hack/update-codegen-sonic.sh new file mode 100755 index 000000000..4b1c69de5 --- /dev/null +++ b/hack/update-codegen-sonic.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +# Copyright 2017 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. +CODEGEN_PKG=${CODEGEN_PKG:-$(cd "${SCRIPT_ROOT}"; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)} + +source "${CODEGEN_PKG}/kube_codegen.sh" + +THIS_PKG="k8s.io/sample-controller" + +kube::codegen::gen_helpers \ + --boilerplate "${SCRIPT_ROOT}/hack/boilerplate.go.txt" \ + "${SCRIPT_ROOT}/pkg/apis" + +kube::codegen::gen_client \ + --with-watch \ + --output-dir "${SCRIPT_ROOT}/pkg/sonick8s/generated" \ + --output-pkg "${THIS_PKG}/pkg/sonick8s/generated" \ + --boilerplate "${SCRIPT_ROOT}/hack/boilerplate.go.txt" \ + "${SCRIPT_ROOT}/pkg/apis" diff --git a/main.go b/main.go index cda6ca198..72060e9f2 100644 --- a/main.go +++ b/main.go @@ -27,9 +27,9 @@ import ( "k8s.io/sample-controller/pkg/signals" // Uncomment the following line to load the gcp plugin (only required to authenticate against GKE clusters). // _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" - - clientset "k8s.io/sample-controller/pkg/generated/clientset/versioned" - informers "k8s.io/sample-controller/pkg/generated/informers/externalversions" +"k8s.io/sample-controller/pkg/controller" + clientset "k8s.io/sample-controller/pkg/sonick8s/generated/clientset/versioned" + informers "k8s.io/sample-controller/pkg/sonick8s/generated/informers/externalversions" ) var ( @@ -66,9 +66,9 @@ func main() { kubeInformerFactory := kubeinformers.NewSharedInformerFactory(kubeClient, time.Second*30) exampleInformerFactory := informers.NewSharedInformerFactory(exampleClient, time.Second*30) - controller := NewController(ctx, kubeClient, exampleClient, + controller := controller.NewController(ctx, kubeClient, exampleClient, kubeInformerFactory.Apps().V1().Deployments(), - exampleInformerFactory.Samplecontroller().V1alpha1().Foos()) + exampleInformerFactory.Sonick8s().V1alpha1().NetworkDevices()) // notice that there is no need to run Start methods in a separate goroutine. (i.e. go kubeInformerFactory.Start(ctx.done()) // Start method is non-blocking and runs all registered informers in a dedicated goroutine. diff --git a/pkg/apis/samplecontroller/v1alpha1/doc.go b/pkg/apis/samplecontroller/v1alpha1/doc.go index e6c135eed..cd897283f 100644 --- a/pkg/apis/samplecontroller/v1alpha1/doc.go +++ b/pkg/apis/samplecontroller/v1alpha1/doc.go @@ -18,4 +18,4 @@ limitations under the License. // +groupName=samplecontroller.k8s.io // Package v1alpha1 is the v1alpha1 version of the API. -package v1alpha1 +package v1alpha1 \ No newline at end of file diff --git a/pkg/apis/samplecontroller/v1alpha1/register.go b/pkg/apis/samplecontroller/v1alpha1/register.go index e8e0a28ef..30f8c13f8 100644 --- a/pkg/apis/samplecontroller/v1alpha1/register.go +++ b/pkg/apis/samplecontroller/v1alpha1/register.go @@ -52,4 +52,4 @@ func addKnownTypes(scheme *runtime.Scheme) error { ) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil -} +} \ No newline at end of file diff --git a/pkg/apis/samplecontroller/v1alpha1/types.go b/pkg/apis/samplecontroller/v1alpha1/types.go index 28774e9f8..9f5e8b456 100644 --- a/pkg/apis/samplecontroller/v1alpha1/types.go +++ b/pkg/apis/samplecontroller/v1alpha1/types.go @@ -23,62 +23,32 @@ import ( // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// NetworkDevice is a specification for a NetworkDevice resource -type NetworkDevice struct { +// Foo is a specification for a Foo resource +type Foo struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Spec NetworkDeviceSpec `json:"spec"` - Status NetworkDeviceStatus `json:"status"` + Spec FooSpec `json:"spec"` + Status FooStatus `json:"status"` } -// NetworkDeviceSpec is the spec for a NetworkDevice resource -type NetworkDeviceSpec struct { - OS OSInfo `json:"os,omitempty"` +// FooSpec is the spec for a Foo resource +type FooSpec struct { + DeploymentName string `json:"deploymentName"` + Replicas *int32 `json:"replicas"` } -type OSInfo struct { - OSType string `json:"os-type,omitempty"` - Version string `json:"version,omitempty"` +// FooStatus is the status for a Foo resource +type FooStatus struct { + AvailableReplicas int32 `json:"availableReplicas"` } -// NetworkDeviceStatus is the status for a NetworkDevice resource -type NetworkDeviceStatus struct { - State string `json:"state,omitempty"` - LastTransitionTime string `json:"lastTransitionTime,omitempty"` - OS OSStatus `json:"os,omitempty"` - Conditions []Condition `json:"conditions,omitempty"` - Operation OperationStatus `json:"operation,omitempty"` -} -// Condition represents a status condition -type Condition struct { - Type string `json:"type,omitempty"` - Status string `json:"status,omitempty"` - LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` - Reason string `json:"reason,omitempty"` - Message string `json:"message,omitempty"` -} - -// OperationStatus describes an operation in status -type OperationStatus struct { - Name string `json:"name,omitempty"` - ID string `json:"id,omitempty"` - Status string `json:"status,omitempty"` - OperationAction OperationAction `json:"operationAction,omitempty"` -} - -// OperationAction describes the action of an operation -type OperationAction struct { - Name string `json:"name,omitempty"` - ID string `json:"id,omitempty"` - Status string `json:"status,omitempty"` -} // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// NetworkDeviceList is a list of NetworkDevice resources -type NetworkDeviceList struct { +// FooList is a list of Foo resources +type FooList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata"` - Items []NetworkDevice `json:"items"` -} + Items []Foo `json:"items"` +} \ No newline at end of file diff --git a/pkg/apis/sonic/register.go b/pkg/apis/sonic/register.go new file mode 100644 index 000000000..19d9370e3 --- /dev/null +++ b/pkg/apis/sonic/register.go @@ -0,0 +1,22 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package sonic + +// GroupName is the group name used in this package +const ( + GroupName = "sonick8s.io" +) diff --git a/pkg/apis/sonic/v1alpha1/doc.go b/pkg/apis/sonic/v1alpha1/doc.go new file mode 100644 index 000000000..0018db8d6 --- /dev/null +++ b/pkg/apis/sonic/v1alpha1/doc.go @@ -0,0 +1,21 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// +k8s:deepcopy-gen=package +// +groupName=sonick8s.io + +// Package v1alpha1 is the v1alpha1 version of the API. +package v1alpha1 diff --git a/pkg/apis/sonic/v1alpha1/register.go b/pkg/apis/sonic/v1alpha1/register.go new file mode 100644 index 000000000..9ede40a5a --- /dev/null +++ b/pkg/apis/sonic/v1alpha1/register.go @@ -0,0 +1,54 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + + sonic "k8s.io/sample-controller/pkg/apis/sonic" +) + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: sonic.GroupName, Version: "v1alpha1"} +// Kind takes an unqualified kind and returns back a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // SchemeBuilder initializes a scheme builder + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + // AddToScheme is a global function that registers this API group & version to a scheme + AddToScheme = SchemeBuilder.AddToScheme +) + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &NetworkDevice{}, + &NetworkDeviceList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/pkg/apis/sonic/v1alpha1/types.go b/pkg/apis/sonic/v1alpha1/types.go new file mode 100644 index 000000000..a7579a51a --- /dev/null +++ b/pkg/apis/sonic/v1alpha1/types.go @@ -0,0 +1,88 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// NetworkDevice is a specification for a NetworkDevice resource +type NetworkDevice struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec NetworkDeviceSpec `json:"spec"` + Status NetworkDeviceStatus `json:"status,omitempty"` +} + +// NetworkDeviceSpec is the spec for a NetworkDevice resource +type NetworkDeviceSpec struct { + OS OSInfo `json:"os,omitempty"` +} + +type OSInfo struct { + OSType string `json:"os-type,omitempty"` + Version string `json:"version,omitempty"` +} + +// NetworkDeviceStatus is the status for a NetworkDevice resource +type NetworkDeviceStatus struct { + State string `json:"state,omitempty"` + LastTransitionTime string `json:"lastTransitionTime,omitempty"` + OS OSInfo `json:"os,omitempty"` + Conditions []Condition `json:"conditions,omitempty"` + Operation *OperationStatus `json:"operation,omitempty"` +} + +// Condition represents a status condition +type Condition struct { + Type string `json:"type,omitempty"` + Status string `json:"status,omitempty"` + LastProbeTime metav1.Time `json:"lastProbeTime,omitempty"` + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` + Reason string `json:"reason,omitempty"` + Message string `json:"message,omitempty"` +} + +// OperationStatus describes an operation in status +type OperationStatus struct { + Name string `json:"name,omitempty"` + ID string `json:"id,omitempty"` + Status string `json:"status,omitempty"` + OperationAction *OperationAction `json:"operationAction,omitempty"` +} + +// OperationAction describes the action of an operation +type OperationAction struct { + Name string `json:"name,omitempty"` + ID string `json:"id,omitempty"` + Status string `json:"status,omitempty"` +} +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// NetworkDeviceList is a list of NetworkDevice resources +// +kubebuilder:object:root=true +type NetworkDeviceList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []NetworkDevice `json:"items"` +} diff --git a/pkg/apis/sonic/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/sonic/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 000000000..6e9982772 --- /dev/null +++ b/pkg/apis/sonic/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,196 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by deepcopy-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 *Condition) DeepCopyInto(out *Condition) { + *out = *in + in.LastProbeTime.DeepCopyInto(&out.LastProbeTime) + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Condition. +func (in *Condition) DeepCopy() *Condition { + if in == nil { + return nil + } + out := new(Condition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkDevice) DeepCopyInto(out *NetworkDevice) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkDevice. +func (in *NetworkDevice) DeepCopy() *NetworkDevice { + if in == nil { + return nil + } + out := new(NetworkDevice) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NetworkDevice) 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 *NetworkDeviceList) DeepCopyInto(out *NetworkDeviceList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]NetworkDevice, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkDeviceList. +func (in *NetworkDeviceList) DeepCopy() *NetworkDeviceList { + if in == nil { + return nil + } + out := new(NetworkDeviceList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NetworkDeviceList) 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 *NetworkDeviceSpec) DeepCopyInto(out *NetworkDeviceSpec) { + *out = *in + out.OS = in.OS + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkDeviceSpec. +func (in *NetworkDeviceSpec) DeepCopy() *NetworkDeviceSpec { + if in == nil { + return nil + } + out := new(NetworkDeviceSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkDeviceStatus) DeepCopyInto(out *NetworkDeviceStatus) { + *out = *in + out.OS = in.OS + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + out.Operation = in.Operation + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkDeviceStatus. +func (in *NetworkDeviceStatus) DeepCopy() *NetworkDeviceStatus { + if in == nil { + return nil + } + out := new(NetworkDeviceStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OSInfo) DeepCopyInto(out *OSInfo) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSInfo. +func (in *OSInfo) DeepCopy() *OSInfo { + if in == nil { + return nil + } + out := new(OSInfo) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OperationAction) DeepCopyInto(out *OperationAction) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OperationAction. +func (in *OperationAction) DeepCopy() *OperationAction { + if in == nil { + return nil + } + out := new(OperationAction) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OperationStatus) DeepCopyInto(out *OperationStatus) { + *out = *in + out.OperationAction = in.OperationAction + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OperationStatus. +func (in *OperationStatus) DeepCopy() *OperationStatus { + if in == nil { + return nil + } + out := new(OperationStatus) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/controller/networkdevice_controller.go b/pkg/controller/networkdevice_controller.go new file mode 100644 index 000000000..520ba1b64 --- /dev/null +++ b/pkg/controller/networkdevice_controller.go @@ -0,0 +1,353 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package controller + +import ( + "context" + "fmt" + "time" + + "golang.org/x/time/rate" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + appsinformers "k8s.io/client-go/informers/apps/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/kubernetes/scheme" + typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1" + appslisters "k8s.io/client-go/listers/apps/v1" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/tools/record" + "k8s.io/client-go/util/workqueue" + "k8s.io/klog/v2" + + samplev1alpha1 "k8s.io/sample-controller/pkg/apis/sonic/v1alpha1" + clientset "k8s.io/sample-controller/pkg/sonick8s/generated/clientset/versioned" + samplescheme "k8s.io/sample-controller/pkg/sonick8s/generated/clientset/versioned/scheme" + informers "k8s.io/sample-controller/pkg/sonick8s/generated/informers/externalversions/sonic/v1alpha1" + listers "k8s.io/sample-controller/pkg/sonick8s/generated/listers/sonic/v1alpha1" +) + +const controllerAgentName = "networkdevice-controller" + +const ( + // SuccessSynced is used as part of the Event 'reason' when a Foo is synced + SuccessSynced = "Synced" + // ErrResourceExists is used as part of the Event 'reason' when a Foo fails + // to sync due to a Deployment of the same name already existing. + ErrResourceExists = "ErrResourceExists" + + // MessageResourceExists is the message used for Events when a resource + // fails to sync due to a Deployment already existing + MessageResourceExists = "Resource %q already exists and is not managed by Foo" + // MessageResourceSynced is the message used for an Event fired when a Foo + // is synced successfully + MessageResourceSynced = "Foo synced successfully" + // FieldManager distinguishes this controller from other things writing to API objects + FieldManager = controllerAgentName +) + +// Controller is the controller implementation for Foo resources +type Controller struct { + // kubeclientset is a standard kubernetes clientset + kubeclientset kubernetes.Interface + // sampleclientset is a clientset for our own API group + sampleclientset clientset.Interface + + deploymentsLister appslisters.DeploymentLister + deploymentsSynced cache.InformerSynced + networkDeviceLister listers.NetworkDeviceLister + networkDevicesSynced cache.InformerSynced + + // workqueue is a rate limited work queue. This is used to queue work to be + // processed instead of performing it as soon as a change happens. This + // means we can ensure we only process a fixed amount of resources at a + // time, and makes it easy to ensure we are never processing the same item + // simultaneously in two different workers. + workqueue workqueue.TypedRateLimitingInterface[cache.ObjectName] + // recorder is an event recorder for recording Event resources to the + // Kubernetes API. + recorder record.EventRecorder +} + +// NewController returns a new sample controller +func NewController( + ctx context.Context, + kubeclientset kubernetes.Interface, + sampleclientset clientset.Interface, + deploymentInformer appsinformers.DeploymentInformer, + networkDeviceInformer informers.NetworkDeviceInformer) *Controller { + logger := klog.FromContext(ctx) + + // Create event broadcaster + // Add sample-controller types to the default Kubernetes Scheme so Events can be + // logged for sample-controller types. + utilruntime.Must(samplescheme.AddToScheme(scheme.Scheme)) + logger.V(4).Info("Creating event broadcaster") + + eventBroadcaster := record.NewBroadcaster(record.WithContext(ctx)) + eventBroadcaster.StartStructuredLogging(0) + eventBroadcaster.StartRecordingToSink(&typedcorev1.EventSinkImpl{Interface: kubeclientset.CoreV1().Events("")}) + recorder := eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: controllerAgentName}) + ratelimiter := workqueue.NewTypedMaxOfRateLimiter( + workqueue.NewTypedItemExponentialFailureRateLimiter[cache.ObjectName](5*time.Millisecond, 1000*time.Second), + &workqueue.TypedBucketRateLimiter[cache.ObjectName]{Limiter: rate.NewLimiter(rate.Limit(50), 300)}, + ) + + controller := &Controller{ + kubeclientset: kubeclientset, + sampleclientset: sampleclientset, + deploymentsLister: deploymentInformer.Lister(), + deploymentsSynced: deploymentInformer.Informer().HasSynced, + networkDeviceLister: networkDeviceInformer.Lister(), + networkDevicesSynced: networkDeviceInformer.Informer().HasSynced, + workqueue: workqueue.NewTypedRateLimitingQueue(ratelimiter), + recorder: recorder, + } + + logger.Info("Setting up event handlers") + // Set up an event handler for when Device resources change + networkDeviceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: controller.enqueueDevice, + UpdateFunc: func(old, new interface{}) { + controller.enqueueDevice(new) + }, + }) + + return controller +} + +// Run will set up the event handlers for types we are interested in, as well +// as syncing informer caches and starting workers. It will block until stopCh +// is closed, at which point it will shutdown the workqueue and wait for +// workers to finish processing their current work items. +func (c *Controller) Run(ctx context.Context, workers int) error { + defer utilruntime.HandleCrash() + defer c.workqueue.ShutDown() + logger := klog.FromContext(ctx) + + // Start the informer factories to begin populating the informer caches + logger.Info("Starting Foo controller") + + // Wait for the caches to be synced before starting workers + logger.Info("Waiting for informer caches to sync") + + if ok := cache.WaitForCacheSync(ctx.Done(), c.deploymentsSynced, c.networkDevicesSynced); !ok { + return fmt.Errorf("failed to wait for caches to sync") + } + + logger.Info("Starting workers", "count", workers) + // Launch two workers to process Foo resources + for i := 0; i < workers; i++ { + go wait.UntilWithContext(ctx, c.runWorker, time.Second) + } + + logger.Info("Started workers") + <-ctx.Done() + logger.Info("Shutting down workers") + + return nil +} + +// runWorker is a long-running function that will continually call the +// processNextWorkItem function in order to read and process a message on the +// workqueue. +func (c *Controller) runWorker(ctx context.Context) { + for c.processNextWorkItem(ctx) { + } +} + +// processNextWorkItem will read a single work item off the workqueue and +// attempt to process it, by calling the syncHandler. +func (c *Controller) processNextWorkItem(ctx context.Context) bool { + objRef, shutdown := c.workqueue.Get() + logger := klog.FromContext(ctx) + + if shutdown { + return false + } + + // We call Done at the end of this func so the workqueue knows we have + // finished processing this item. We also must remember to call Forget + // if we do not want this work item being re-queued. For example, we do + // not call Forget if a transient error occurs, instead the item is + // put back on the workqueue and attempted again after a back-off + // period. + defer c.workqueue.Done(objRef) + + // Run the syncHandler, passing it the structured reference to the object to be synced. + err := c.syncHandler(ctx, objRef) + if err == nil { + // If no error occurs then we Forget this item so it does not + // get queued again until another change happens. + c.workqueue.Forget(objRef) + logger.Info("Successfully synced", "objectName", objRef) + return true + } + // there was a failure so be sure to report it. This method allows for + // pluggable error handling which can be used for things like + // cluster-monitoring. + utilruntime.HandleErrorWithContext(ctx, err, "Error syncing; requeuing for later retry", "objectReference", objRef) + // since we failed, we should requeue the item to work on later. This + // method will add a backoff to avoid hotlooping on particular items + // (they're probably still not going to work right away) and overall + // controller protection (everything I've done is broken, this controller + // needs to calm down or it can starve other useful work) cases. + c.workqueue.AddRateLimited(objRef) + return true +} + +// syncHandler compares the actual state with the desired, and attempts to +// converge the two. It then updates the Status block of the Foo resource +// with the current status of the resource. +func (c *Controller) syncHandler(ctx context.Context, objectRef cache.ObjectName) error { + logger := klog.LoggerWithValues(klog.FromContext(ctx), "objectRef", objectRef) + + // Get the NetworkDevice resource with this namespace/name + device, err := c.networkDeviceLister.NetworkDevices(objectRef.Namespace).Get(objectRef.Name) + if err != nil { + // The NetworkDevice resource may no longer exist, in which case we stop + // processing. + if errors.IsNotFound(err) { + utilruntime.HandleErrorWithContext(ctx, err, "NetworkDevice referenced by item in work queue no longer exists", "objectReference", objectRef) + return nil + } + + return err + } + + // if device has no status or no operation, nothing to do + if device.Status.Operation == nil { + logger.Info("NetworkDevice has no operation defined, skipping processing") + return nil + } + + // only handle OSUpgradeOperation operations for demo purposes + if device.Status.Operation.Name != "OSUpgradeOperation" { + logger.Info("Ignoring NetworkDevice with unsupported operation type", "operationType", device.Status.Operation.Name) + return nil + } + + operationHandler := NewOSUpgradeOperation() + + if !operationHandler.Proceed(&device) { + logger.Info("Operation action state is not 'Proceed', skipping processing", "status", device.Status) + return nil + } + + // move to the next action + nextAction, hasNext := operationHandler.NextAction(&device) + if hasNext { + logger.Info("Moving to next action", "nextAction", nextAction) + if device.Status.Operation.OperationAction == nil { + device.Status.Operation.OperationAction = &samplev1alpha1.OperationAction{} + } + device.Status.Operation.OperationAction.Name = nextAction + device.Status.Operation.OperationAction.Status = "Pending" + } else { + logger.Info("No more actions left, marking operation as Completed") + device.Status.Operation.Status = "Completed" + } + + c.updateNetworkDeviceStatus(ctx, device) + // just logging for demo purposes + logger.Info("Processing NetworkDevice", "deviceSpec", device.Spec, "deviceStatus", device.Status) + + c.recorder.Event(device, corev1.EventTypeNormal, SuccessSynced, MessageResourceSynced) + return nil +} + +func (c *Controller) updateNetworkDeviceStatus(ctx context.Context, device *samplev1alpha1.NetworkDevice) error { + // NEVER modify objects from the store. It's a read-only, local cache. + // You can use DeepCopy() to make a deep copy of original object and modify this copy + // Or create a copy manually for better performance + deviceCopy := device.DeepCopy() + deviceCopy.Status.State = "Healthy" + if deviceCopy.Status.LastTransitionTime == "" { + deviceCopy.Status.LastTransitionTime = time.Now().Format(time.RFC3339) + } + // set the os info in status to match spec for demo purposes + deviceCopy.Status.OS = deviceCopy.Spec.OS + + // logging the status update for demo purposes + logger := klog.FromContext(ctx) + msg := fmt.Sprintf("Updating NetworkDevice %s status to %v", deviceCopy.Name, deviceCopy.Status.Operation) + logger.Info(msg) + + _, err := c.sampleclientset.Sonick8sV1alpha1().NetworkDevices(device.Namespace).UpdateStatus(ctx, deviceCopy, metav1.UpdateOptions{FieldManager: FieldManager}) + return err +} + +// enqueueDevice takes a Device resource and converts it into a namespace/name +// string which is then put onto the work queue. This method should *not* be +// passed resources of any type other than Device. +func (c *Controller) enqueueDevice(obj interface{}) { + if objectRef, err := cache.ObjectToName(obj); err != nil { + utilruntime.HandleError(err) + return + } else { + c.workqueue.Add(objectRef) + } +} + +// handleObject will take any resource implementing metav1.Object and attempt +// to find the Device resource that 'owns' it. It does this by looking at the +// objects metadata.ownerReferences field for an appropriate OwnerReference. +// It then enqueues that Device resource to be processed. If the object does not +// have an appropriate OwnerReference, it will simply be skipped. +func (c *Controller) handleObject(obj interface{}) { + var object metav1.Object + var ok bool + logger := klog.FromContext(context.Background()) + if object, ok = obj.(metav1.Object); !ok { + tombstone, ok := obj.(cache.DeletedFinalStateUnknown) + if !ok { + // If the object value is not too big and does not contain sensitive information then + // it may be useful to include it. + utilruntime.HandleErrorWithContext(context.Background(), nil, "Error decoding object, invalid type", "type", fmt.Sprintf("%T", obj)) + return + } + object, ok = tombstone.Obj.(metav1.Object) + if !ok { + // If the object value is not too big and does not contain sensitive information then + // it may be useful to include it. + utilruntime.HandleErrorWithContext(context.Background(), nil, "Error decoding object tombstone, invalid type", "type", fmt.Sprintf("%T", tombstone.Obj)) + return + } + logger.V(4).Info("Recovered deleted object", "resourceName", object.GetName()) + } + logger.V(4).Info("Processing object", "object", klog.KObj(object)) + if ownerRef := metav1.GetControllerOf(object); ownerRef != nil { + // If this object is not owned by a Foo, we should not do anything more + // with it. + if ownerRef.Kind != "Foo" { + return + } + + networkDevice, err := c.networkDeviceLister.NetworkDevices(object.GetNamespace()).Get(ownerRef.Name) + if err != nil { + logger.V(4).Info("Ignore orphaned object", "object", klog.KObj(networkDevice), "networkDevice", ownerRef.Name) + return + } + + c.enqueueDevice(networkDevice) + return + } +} diff --git a/pkg/controller/operation.go b/pkg/controller/operation.go new file mode 100644 index 000000000..8a1fa1466 --- /dev/null +++ b/pkg/controller/operation.go @@ -0,0 +1,62 @@ +package controller + +import ( + samplev1alpha1 "k8s.io/sample-controller/pkg/apis/sonic/v1alpha1" +) + +// define an interface for operation handling +type OperationHandler interface { + Proceed(device *samplev1alpha1.NetworkDevice) bool + NextAction(device *samplev1alpha1.NetworkDevice) (string, bool) +} + +type OSUpgradeOperation struct { + Actions []string +} + +// NewOSUpgradeOperation creates a new operation with the defined actions +func NewOSUpgradeOperation() *OSUpgradeOperation { + return &OSUpgradeOperation{ + Actions: []string{ + "Safetycheck", + "Deviceisolation", + "Preloadimage", + "Setbootpartition", + "Rebootdevice", + }, + } +} + +// Proceed checks if the current action's state is "proceed" +func (op *OSUpgradeOperation) Proceed(device **samplev1alpha1.NetworkDevice) bool { + // if no operation action is defined, cannot proceed + deviceStatus := (*device).Status + if deviceStatus.Operation == nil { + return false + } + + if deviceStatus.Operation.OperationAction == nil { + return true + } + return deviceStatus.Operation.OperationAction.Status == "Proceed" +} + +// NextAction returns the next action after the current one +func (op *OSUpgradeOperation) NextAction(device **samplev1alpha1.NetworkDevice) (string, bool) { + // if no operation action is defined, return the first action + deviceStatus := (*device).Status + if deviceStatus.Operation == nil || deviceStatus.Operation.OperationAction == nil { + return op.Actions[0], true + } + + for i, action := range op.Actions { + if action == deviceStatus.Operation.OperationAction.Name { + if i+1 < len(op.Actions) { + return op.Actions[i+1], true + } + return "", false // No next action + } + } + // If current action is not found, return the first action + return op.Actions[0], true +} diff --git a/pkg/sonick8s/generated/clientset/versioned/clientset.go b/pkg/sonick8s/generated/clientset/versioned/clientset.go new file mode 100644 index 000000000..61da9ba8e --- /dev/null +++ b/pkg/sonick8s/generated/clientset/versioned/clientset.go @@ -0,0 +1,133 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package versioned + +import ( + fmt "fmt" + http "net/http" + + discovery "k8s.io/client-go/discovery" + rest "k8s.io/client-go/rest" + flowcontrol "k8s.io/client-go/util/flowcontrol" + samplecontrollerv1alpha1 "k8s.io/sample-controller/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1" + sonick8sv1alpha1 "k8s.io/sample-controller/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1" +) + +type Interface interface { + Discovery() discovery.DiscoveryInterface + SamplecontrollerV1alpha1() samplecontrollerv1alpha1.SamplecontrollerV1alpha1Interface + Sonick8sV1alpha1() sonick8sv1alpha1.Sonick8sV1alpha1Interface +} + +// Clientset contains the clients for groups. +type Clientset struct { + *discovery.DiscoveryClient + samplecontrollerV1alpha1 *samplecontrollerv1alpha1.SamplecontrollerV1alpha1Client + sonick8sV1alpha1 *sonick8sv1alpha1.Sonick8sV1alpha1Client +} + +// SamplecontrollerV1alpha1 retrieves the SamplecontrollerV1alpha1Client +func (c *Clientset) SamplecontrollerV1alpha1() samplecontrollerv1alpha1.SamplecontrollerV1alpha1Interface { + return c.samplecontrollerV1alpha1 +} + +// Sonick8sV1alpha1 retrieves the Sonick8sV1alpha1Client +func (c *Clientset) Sonick8sV1alpha1() sonick8sv1alpha1.Sonick8sV1alpha1Interface { + return c.sonick8sV1alpha1 +} + +// Discovery retrieves the DiscoveryClient +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + if c == nil { + return nil + } + return c.DiscoveryClient +} + +// NewForConfig creates a new Clientset for the given config. +// If config's RateLimiter is not set and QPS and Burst are acceptable, +// NewForConfig will generate a rate-limiter in configShallowCopy. +// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), +// where httpClient was generated with rest.HTTPClientFor(c). +func NewForConfig(c *rest.Config) (*Clientset, error) { + configShallowCopy := *c + + if configShallowCopy.UserAgent == "" { + configShallowCopy.UserAgent = rest.DefaultKubernetesUserAgent() + } + + // share the transport between all clients + httpClient, err := rest.HTTPClientFor(&configShallowCopy) + if err != nil { + return nil, err + } + + return NewForConfigAndClient(&configShallowCopy, httpClient) +} + +// NewForConfigAndClient creates a new Clientset for the given config and http client. +// Note the http client provided takes precedence over the configured transport values. +// If config's RateLimiter is not set and QPS and Burst are acceptable, +// NewForConfigAndClient will generate a rate-limiter in configShallowCopy. +func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, error) { + configShallowCopy := *c + if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { + if configShallowCopy.Burst <= 0 { + return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0") + } + configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) + } + + var cs Clientset + var err error + cs.samplecontrollerV1alpha1, err = samplecontrollerv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient) + if err != nil { + return nil, err + } + cs.sonick8sV1alpha1, err = sonick8sv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient) + if err != nil { + return nil, err + } + + cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfigAndClient(&configShallowCopy, httpClient) + if err != nil { + return nil, err + } + return &cs, nil +} + +// NewForConfigOrDie creates a new Clientset for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *Clientset { + cs, err := NewForConfig(c) + if err != nil { + panic(err) + } + return cs +} + +// New creates a new Clientset for the given RESTClient. +func New(c rest.Interface) *Clientset { + var cs Clientset + cs.samplecontrollerV1alpha1 = samplecontrollerv1alpha1.New(c) + cs.sonick8sV1alpha1 = sonick8sv1alpha1.New(c) + + cs.DiscoveryClient = discovery.NewDiscoveryClient(c) + return &cs +} diff --git a/pkg/sonick8s/generated/clientset/versioned/fake/clientset_generated.go b/pkg/sonick8s/generated/clientset/versioned/fake/clientset_generated.go new file mode 100644 index 000000000..e9f562619 --- /dev/null +++ b/pkg/sonick8s/generated/clientset/versioned/fake/clientset_generated.go @@ -0,0 +1,112 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/discovery" + fakediscovery "k8s.io/client-go/discovery/fake" + "k8s.io/client-go/testing" + clientset "k8s.io/sample-controller/pkg/sonick8s/generated/clientset/versioned" + samplecontrollerv1alpha1 "k8s.io/sample-controller/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1" + fakesamplecontrollerv1alpha1 "k8s.io/sample-controller/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/fake" + sonick8sv1alpha1 "k8s.io/sample-controller/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1" + fakesonick8sv1alpha1 "k8s.io/sample-controller/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/fake" +) + +// NewSimpleClientset returns a clientset that will respond with the provided objects. +// It's backed by a very simple object tracker that processes creates, updates and deletions as-is, +// without applying any field management, validations and/or defaults. It shouldn't be considered a replacement +// for a real clientset and is mostly useful in simple unit tests. +// +// Deprecated: NewClientset replaces this with support for field management, which significantly improves +// server side apply testing. NewClientset is only available when apply configurations are generated (e.g. +// via --with-applyconfig). +func NewSimpleClientset(objects ...runtime.Object) *Clientset { + o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) + for _, obj := range objects { + if err := o.Add(obj); err != nil { + panic(err) + } + } + + cs := &Clientset{tracker: o} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + var opts metav1.ListOptions + if watchAction, ok := action.(testing.WatchActionImpl); ok { + opts = watchAction.ListOptions + } + gvr := action.GetResource() + ns := action.GetNamespace() + watch, err := o.Watch(gvr, ns, opts) + if err != nil { + return false, nil, err + } + return true, watch, nil + }) + + return cs +} + +// Clientset implements clientset.Interface. Meant to be embedded into a +// struct to get a default implementation. This makes faking out just the method +// you want to test easier. +type Clientset struct { + testing.Fake + discovery *fakediscovery.FakeDiscovery + tracker testing.ObjectTracker +} + +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + return c.discovery +} + +func (c *Clientset) Tracker() testing.ObjectTracker { + return c.tracker +} + +// IsWatchListSemanticsSupported informs the reflector that this client +// doesn't support WatchList semantics. +// +// This is a synthetic method whose sole purpose is to satisfy the optional +// interface check performed by the reflector. +// Returning true signals that WatchList can NOT be used. +// No additional logic is implemented here. +func (c *Clientset) IsWatchListSemanticsUnSupported() bool { + return true +} + +var ( + _ clientset.Interface = &Clientset{} + _ testing.FakeClient = &Clientset{} +) + +// SamplecontrollerV1alpha1 retrieves the SamplecontrollerV1alpha1Client +func (c *Clientset) SamplecontrollerV1alpha1() samplecontrollerv1alpha1.SamplecontrollerV1alpha1Interface { + return &fakesamplecontrollerv1alpha1.FakeSamplecontrollerV1alpha1{Fake: &c.Fake} +} + +// Sonick8sV1alpha1 retrieves the Sonick8sV1alpha1Client +func (c *Clientset) Sonick8sV1alpha1() sonick8sv1alpha1.Sonick8sV1alpha1Interface { + return &fakesonick8sv1alpha1.FakeSonick8sV1alpha1{Fake: &c.Fake} +} diff --git a/pkg/sonick8s/generated/clientset/versioned/fake/doc.go b/pkg/sonick8s/generated/clientset/versioned/fake/doc.go new file mode 100644 index 000000000..9b99e7167 --- /dev/null +++ b/pkg/sonick8s/generated/clientset/versioned/fake/doc.go @@ -0,0 +1,20 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated fake clientset. +package fake diff --git a/pkg/sonick8s/generated/clientset/versioned/fake/register.go b/pkg/sonick8s/generated/clientset/versioned/fake/register.go new file mode 100644 index 000000000..09e8fe73f --- /dev/null +++ b/pkg/sonick8s/generated/clientset/versioned/fake/register.go @@ -0,0 +1,58 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + samplecontrollerv1alpha1 "k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1" + sonick8sv1alpha1 "k8s.io/sample-controller/pkg/apis/sonic/v1alpha1" +) + +var scheme = runtime.NewScheme() +var codecs = serializer.NewCodecFactory(scheme) + +var localSchemeBuilder = runtime.SchemeBuilder{ + samplecontrollerv1alpha1.AddToScheme, + sonick8sv1alpha1.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(AddToScheme(scheme)) +} diff --git a/pkg/sonick8s/generated/clientset/versioned/scheme/doc.go b/pkg/sonick8s/generated/clientset/versioned/scheme/doc.go new file mode 100644 index 000000000..7dc375616 --- /dev/null +++ b/pkg/sonick8s/generated/clientset/versioned/scheme/doc.go @@ -0,0 +1,20 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// This package contains the scheme of the automatically generated clientset. +package scheme diff --git a/pkg/sonick8s/generated/clientset/versioned/scheme/register.go b/pkg/sonick8s/generated/clientset/versioned/scheme/register.go new file mode 100644 index 000000000..da9598c58 --- /dev/null +++ b/pkg/sonick8s/generated/clientset/versioned/scheme/register.go @@ -0,0 +1,58 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package scheme + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + samplecontrollerv1alpha1 "k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1" + sonick8sv1alpha1 "k8s.io/sample-controller/pkg/apis/sonic/v1alpha1" +) + +var Scheme = runtime.NewScheme() +var Codecs = serializer.NewCodecFactory(Scheme) +var ParameterCodec = runtime.NewParameterCodec(Scheme) +var localSchemeBuilder = runtime.SchemeBuilder{ + samplecontrollerv1alpha1.AddToScheme, + sonick8sv1alpha1.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(AddToScheme(Scheme)) +} diff --git a/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/doc.go b/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/doc.go new file mode 100644 index 000000000..df51baa4d --- /dev/null +++ b/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/doc.go @@ -0,0 +1,20 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1alpha1 diff --git a/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/fake/doc.go b/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/fake/doc.go new file mode 100644 index 000000000..16f443990 --- /dev/null +++ b/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/fake/doc.go @@ -0,0 +1,20 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/fake/fake_foo.go b/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/fake/fake_foo.go new file mode 100644 index 000000000..fd090f6e2 --- /dev/null +++ b/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/fake/fake_foo.go @@ -0,0 +1,48 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + gentype "k8s.io/client-go/gentype" + v1alpha1 "k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1" + samplecontrollerv1alpha1 "k8s.io/sample-controller/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1" +) + +// fakeFoos implements FooInterface +type fakeFoos struct { + *gentype.FakeClientWithList[*v1alpha1.Foo, *v1alpha1.FooList] + Fake *FakeSamplecontrollerV1alpha1 +} + +func newFakeFoos(fake *FakeSamplecontrollerV1alpha1, namespace string) samplecontrollerv1alpha1.FooInterface { + return &fakeFoos{ + gentype.NewFakeClientWithList[*v1alpha1.Foo, *v1alpha1.FooList]( + fake.Fake, + namespace, + v1alpha1.SchemeGroupVersion.WithResource("foos"), + v1alpha1.SchemeGroupVersion.WithKind("Foo"), + func() *v1alpha1.Foo { return &v1alpha1.Foo{} }, + func() *v1alpha1.FooList { return &v1alpha1.FooList{} }, + func(dst, src *v1alpha1.FooList) { dst.ListMeta = src.ListMeta }, + func(list *v1alpha1.FooList) []*v1alpha1.Foo { return gentype.ToPointerSlice(list.Items) }, + func(list *v1alpha1.FooList, items []*v1alpha1.Foo) { list.Items = gentype.FromPointerSlice(items) }, + ), + fake, + } +} diff --git a/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/fake/fake_samplecontroller_client.go b/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/fake/fake_samplecontroller_client.go new file mode 100644 index 000000000..d493275cc --- /dev/null +++ b/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/fake/fake_samplecontroller_client.go @@ -0,0 +1,40 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" + v1alpha1 "k8s.io/sample-controller/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1" +) + +type FakeSamplecontrollerV1alpha1 struct { + *testing.Fake +} + +func (c *FakeSamplecontrollerV1alpha1) Foos(namespace string) v1alpha1.FooInterface { + return newFakeFoos(c, namespace) +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeSamplecontrollerV1alpha1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/foo.go b/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/foo.go new file mode 100644 index 000000000..8e1257ef1 --- /dev/null +++ b/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/foo.go @@ -0,0 +1,70 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + context "context" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + gentype "k8s.io/client-go/gentype" + samplecontrollerv1alpha1 "k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1" + scheme "k8s.io/sample-controller/pkg/sonick8s/generated/clientset/versioned/scheme" +) + +// FoosGetter has a method to return a FooInterface. +// A group's client should implement this interface. +type FoosGetter interface { + Foos(namespace string) FooInterface +} + +// FooInterface has methods to work with Foo resources. +type FooInterface interface { + Create(ctx context.Context, foo *samplecontrollerv1alpha1.Foo, opts v1.CreateOptions) (*samplecontrollerv1alpha1.Foo, error) + Update(ctx context.Context, foo *samplecontrollerv1alpha1.Foo, opts v1.UpdateOptions) (*samplecontrollerv1alpha1.Foo, error) + // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + UpdateStatus(ctx context.Context, foo *samplecontrollerv1alpha1.Foo, opts v1.UpdateOptions) (*samplecontrollerv1alpha1.Foo, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*samplecontrollerv1alpha1.Foo, error) + List(ctx context.Context, opts v1.ListOptions) (*samplecontrollerv1alpha1.FooList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *samplecontrollerv1alpha1.Foo, err error) + FooExpansion +} + +// foos implements FooInterface +type foos struct { + *gentype.ClientWithList[*samplecontrollerv1alpha1.Foo, *samplecontrollerv1alpha1.FooList] +} + +// newFoos returns a Foos +func newFoos(c *SamplecontrollerV1alpha1Client, namespace string) *foos { + return &foos{ + gentype.NewClientWithList[*samplecontrollerv1alpha1.Foo, *samplecontrollerv1alpha1.FooList]( + "foos", + c.RESTClient(), + scheme.ParameterCodec, + namespace, + func() *samplecontrollerv1alpha1.Foo { return &samplecontrollerv1alpha1.Foo{} }, + func() *samplecontrollerv1alpha1.FooList { return &samplecontrollerv1alpha1.FooList{} }, + ), + } +} diff --git a/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/generated_expansion.go b/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/generated_expansion.go new file mode 100644 index 000000000..b64ea0250 --- /dev/null +++ b/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/generated_expansion.go @@ -0,0 +1,21 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +type FooExpansion interface{} diff --git a/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/samplecontroller_client.go b/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/samplecontroller_client.go new file mode 100644 index 000000000..ac1bf29a4 --- /dev/null +++ b/pkg/sonick8s/generated/clientset/versioned/typed/samplecontroller/v1alpha1/samplecontroller_client.go @@ -0,0 +1,101 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + http "net/http" + + rest "k8s.io/client-go/rest" + samplecontrollerv1alpha1 "k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1" + scheme "k8s.io/sample-controller/pkg/sonick8s/generated/clientset/versioned/scheme" +) + +type SamplecontrollerV1alpha1Interface interface { + RESTClient() rest.Interface + FoosGetter +} + +// SamplecontrollerV1alpha1Client is used to interact with features provided by the samplecontroller.k8s.io group. +type SamplecontrollerV1alpha1Client struct { + restClient rest.Interface +} + +func (c *SamplecontrollerV1alpha1Client) Foos(namespace string) FooInterface { + return newFoos(c, namespace) +} + +// NewForConfig creates a new SamplecontrollerV1alpha1Client for the given config. +// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), +// where httpClient was generated with rest.HTTPClientFor(c). +func NewForConfig(c *rest.Config) (*SamplecontrollerV1alpha1Client, error) { + config := *c + setConfigDefaults(&config) + httpClient, err := rest.HTTPClientFor(&config) + if err != nil { + return nil, err + } + return NewForConfigAndClient(&config, httpClient) +} + +// NewForConfigAndClient creates a new SamplecontrollerV1alpha1Client for the given config and http client. +// Note the http client provided takes precedence over the configured transport values. +func NewForConfigAndClient(c *rest.Config, h *http.Client) (*SamplecontrollerV1alpha1Client, error) { + config := *c + setConfigDefaults(&config) + client, err := rest.RESTClientForConfigAndClient(&config, h) + if err != nil { + return nil, err + } + return &SamplecontrollerV1alpha1Client{client}, nil +} + +// NewForConfigOrDie creates a new SamplecontrollerV1alpha1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *SamplecontrollerV1alpha1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new SamplecontrollerV1alpha1Client for the given RESTClient. +func New(c rest.Interface) *SamplecontrollerV1alpha1Client { + return &SamplecontrollerV1alpha1Client{c} +} + +func setConfigDefaults(config *rest.Config) { + gv := samplecontrollerv1alpha1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = rest.CodecFactoryForGeneratedClient(scheme.Scheme, scheme.Codecs).WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *SamplecontrollerV1alpha1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/doc.go b/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/doc.go new file mode 100644 index 000000000..df51baa4d --- /dev/null +++ b/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/doc.go @@ -0,0 +1,20 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1alpha1 diff --git a/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/fake/doc.go b/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/fake/doc.go new file mode 100644 index 000000000..16f443990 --- /dev/null +++ b/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/fake/doc.go @@ -0,0 +1,20 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/fake/fake_networkdevice.go b/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/fake/fake_networkdevice.go new file mode 100644 index 000000000..04a211543 --- /dev/null +++ b/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/fake/fake_networkdevice.go @@ -0,0 +1,52 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + gentype "k8s.io/client-go/gentype" + v1alpha1 "k8s.io/sample-controller/pkg/apis/sonic/v1alpha1" + sonicv1alpha1 "k8s.io/sample-controller/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1" +) + +// fakeNetworkDevices implements NetworkDeviceInterface +type fakeNetworkDevices struct { + *gentype.FakeClientWithList[*v1alpha1.NetworkDevice, *v1alpha1.NetworkDeviceList] + Fake *FakeSonick8sV1alpha1 +} + +func newFakeNetworkDevices(fake *FakeSonick8sV1alpha1, namespace string) sonicv1alpha1.NetworkDeviceInterface { + return &fakeNetworkDevices{ + gentype.NewFakeClientWithList[*v1alpha1.NetworkDevice, *v1alpha1.NetworkDeviceList]( + fake.Fake, + namespace, + v1alpha1.SchemeGroupVersion.WithResource("networkdevices"), + v1alpha1.SchemeGroupVersion.WithKind("NetworkDevice"), + func() *v1alpha1.NetworkDevice { return &v1alpha1.NetworkDevice{} }, + func() *v1alpha1.NetworkDeviceList { return &v1alpha1.NetworkDeviceList{} }, + func(dst, src *v1alpha1.NetworkDeviceList) { dst.ListMeta = src.ListMeta }, + func(list *v1alpha1.NetworkDeviceList) []*v1alpha1.NetworkDevice { + return gentype.ToPointerSlice(list.Items) + }, + func(list *v1alpha1.NetworkDeviceList, items []*v1alpha1.NetworkDevice) { + list.Items = gentype.FromPointerSlice(items) + }, + ), + fake, + } +} diff --git a/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/fake/fake_sonic_client.go b/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/fake/fake_sonic_client.go new file mode 100644 index 000000000..5be017d17 --- /dev/null +++ b/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/fake/fake_sonic_client.go @@ -0,0 +1,40 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" + v1alpha1 "k8s.io/sample-controller/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1" +) + +type FakeSonick8sV1alpha1 struct { + *testing.Fake +} + +func (c *FakeSonick8sV1alpha1) NetworkDevices(namespace string) v1alpha1.NetworkDeviceInterface { + return newFakeNetworkDevices(c, namespace) +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeSonick8sV1alpha1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/generated_expansion.go b/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/generated_expansion.go new file mode 100644 index 000000000..910b939a6 --- /dev/null +++ b/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/generated_expansion.go @@ -0,0 +1,21 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +type NetworkDeviceExpansion interface{} diff --git a/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/networkdevice.go b/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/networkdevice.go new file mode 100644 index 000000000..2e2ab192d --- /dev/null +++ b/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/networkdevice.go @@ -0,0 +1,70 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + context "context" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + gentype "k8s.io/client-go/gentype" + sonicv1alpha1 "k8s.io/sample-controller/pkg/apis/sonic/v1alpha1" + scheme "k8s.io/sample-controller/pkg/sonick8s/generated/clientset/versioned/scheme" +) + +// NetworkDevicesGetter has a method to return a NetworkDeviceInterface. +// A group's client should implement this interface. +type NetworkDevicesGetter interface { + NetworkDevices(namespace string) NetworkDeviceInterface +} + +// NetworkDeviceInterface has methods to work with NetworkDevice resources. +type NetworkDeviceInterface interface { + Create(ctx context.Context, networkDevice *sonicv1alpha1.NetworkDevice, opts v1.CreateOptions) (*sonicv1alpha1.NetworkDevice, error) + Update(ctx context.Context, networkDevice *sonicv1alpha1.NetworkDevice, opts v1.UpdateOptions) (*sonicv1alpha1.NetworkDevice, error) + // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + UpdateStatus(ctx context.Context, networkDevice *sonicv1alpha1.NetworkDevice, opts v1.UpdateOptions) (*sonicv1alpha1.NetworkDevice, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*sonicv1alpha1.NetworkDevice, error) + List(ctx context.Context, opts v1.ListOptions) (*sonicv1alpha1.NetworkDeviceList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *sonicv1alpha1.NetworkDevice, err error) + NetworkDeviceExpansion +} + +// networkDevices implements NetworkDeviceInterface +type networkDevices struct { + *gentype.ClientWithList[*sonicv1alpha1.NetworkDevice, *sonicv1alpha1.NetworkDeviceList] +} + +// newNetworkDevices returns a NetworkDevices +func newNetworkDevices(c *Sonick8sV1alpha1Client, namespace string) *networkDevices { + return &networkDevices{ + gentype.NewClientWithList[*sonicv1alpha1.NetworkDevice, *sonicv1alpha1.NetworkDeviceList]( + "networkdevices", + c.RESTClient(), + scheme.ParameterCodec, + namespace, + func() *sonicv1alpha1.NetworkDevice { return &sonicv1alpha1.NetworkDevice{} }, + func() *sonicv1alpha1.NetworkDeviceList { return &sonicv1alpha1.NetworkDeviceList{} }, + ), + } +} diff --git a/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/sonic_client.go b/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/sonic_client.go new file mode 100644 index 000000000..6a29feccb --- /dev/null +++ b/pkg/sonick8s/generated/clientset/versioned/typed/sonic/v1alpha1/sonic_client.go @@ -0,0 +1,101 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + http "net/http" + + rest "k8s.io/client-go/rest" + sonicv1alpha1 "k8s.io/sample-controller/pkg/apis/sonic/v1alpha1" + scheme "k8s.io/sample-controller/pkg/sonick8s/generated/clientset/versioned/scheme" +) + +type Sonick8sV1alpha1Interface interface { + RESTClient() rest.Interface + NetworkDevicesGetter +} + +// Sonick8sV1alpha1Client is used to interact with features provided by the sonick8s.io group. +type Sonick8sV1alpha1Client struct { + restClient rest.Interface +} + +func (c *Sonick8sV1alpha1Client) NetworkDevices(namespace string) NetworkDeviceInterface { + return newNetworkDevices(c, namespace) +} + +// NewForConfig creates a new Sonick8sV1alpha1Client for the given config. +// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), +// where httpClient was generated with rest.HTTPClientFor(c). +func NewForConfig(c *rest.Config) (*Sonick8sV1alpha1Client, error) { + config := *c + setConfigDefaults(&config) + httpClient, err := rest.HTTPClientFor(&config) + if err != nil { + return nil, err + } + return NewForConfigAndClient(&config, httpClient) +} + +// NewForConfigAndClient creates a new Sonick8sV1alpha1Client for the given config and http client. +// Note the http client provided takes precedence over the configured transport values. +func NewForConfigAndClient(c *rest.Config, h *http.Client) (*Sonick8sV1alpha1Client, error) { + config := *c + setConfigDefaults(&config) + client, err := rest.RESTClientForConfigAndClient(&config, h) + if err != nil { + return nil, err + } + return &Sonick8sV1alpha1Client{client}, nil +} + +// NewForConfigOrDie creates a new Sonick8sV1alpha1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *Sonick8sV1alpha1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new Sonick8sV1alpha1Client for the given RESTClient. +func New(c rest.Interface) *Sonick8sV1alpha1Client { + return &Sonick8sV1alpha1Client{c} +} + +func setConfigDefaults(config *rest.Config) { + gv := sonicv1alpha1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = rest.CodecFactoryForGeneratedClient(scheme.Scheme, scheme.Codecs).WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *Sonick8sV1alpha1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/pkg/sonick8s/generated/informers/externalversions/factory.go b/pkg/sonick8s/generated/informers/externalversions/factory.go new file mode 100644 index 000000000..8c89ffef2 --- /dev/null +++ b/pkg/sonick8s/generated/informers/externalversions/factory.go @@ -0,0 +1,269 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package externalversions + +import ( + reflect "reflect" + sync "sync" + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" + versioned "k8s.io/sample-controller/pkg/sonick8s/generated/clientset/versioned" + internalinterfaces "k8s.io/sample-controller/pkg/sonick8s/generated/informers/externalversions/internalinterfaces" + samplecontroller "k8s.io/sample-controller/pkg/sonick8s/generated/informers/externalversions/samplecontroller" + sonic "k8s.io/sample-controller/pkg/sonick8s/generated/informers/externalversions/sonic" +) + +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + +type sharedInformerFactory struct { + client versioned.Interface + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc + lock sync.Mutex + defaultResync time.Duration + customResync map[reflect.Type]time.Duration + transform cache.TransformFunc + + informers map[reflect.Type]cache.SharedIndexInformer + // startedInformers is used for tracking which informers have been started. + // This allows Start() to be called multiple times safely. + startedInformers map[reflect.Type]bool + // wg tracks how many goroutines were started. + wg sync.WaitGroup + // shuttingDown is true when Shutdown has been called. It may still be running + // because it needs to wait for goroutines. + shuttingDown bool +} + +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// WithTransform sets a transform on all informers. +func WithTransform(transform cache.TransformFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.transform = transform + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. +func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync) +} + +// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. +// Listers obtained via this SharedInformerFactory will be subject to the same filters +// as specified here. +// +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead +func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ + client: client, + namespace: v1.NamespaceAll, + defaultResync: defaultResync, + informers: make(map[reflect.Type]cache.SharedIndexInformer), + startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) + } + + return factory +} + +func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { + f.lock.Lock() + defer f.lock.Unlock() + + if f.shuttingDown { + return + } + + for informerType, informer := range f.informers { + if !f.startedInformers[informerType] { + f.wg.Add(1) + // We need a new variable in each loop iteration, + // otherwise the goroutine would use the loop variable + // and that keeps changing. + informer := informer + go func() { + defer f.wg.Done() + informer.Run(stopCh) + }() + f.startedInformers[informerType] = true + } + } +} + +func (f *sharedInformerFactory) Shutdown() { + f.lock.Lock() + f.shuttingDown = true + f.lock.Unlock() + + // Will return immediately if there is nothing to wait for. + f.wg.Wait() +} + +func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { + informers := func() map[reflect.Type]cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informers := map[reflect.Type]cache.SharedIndexInformer{} + for informerType, informer := range f.informers { + if f.startedInformers[informerType] { + informers[informerType] = informer + } + } + return informers + }() + + res := map[reflect.Type]bool{} + for informType, informer := range informers { + res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced) + } + return res +} + +// InformerFor returns the SharedIndexInformer for obj using an internal +// client. +func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informerType := reflect.TypeOf(obj) + informer, exists := f.informers[informerType] + if exists { + return informer + } + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) + informer.SetTransform(f.transform) + f.informers[informerType] = informer + + return informer +} + +// SharedInformerFactory provides shared informers for resources in all known +// API group versions. +// +// It is typically used like this: +// +// ctx, cancel := context.WithCancel(context.Background()) +// defer cancel() +// factory := NewSharedInformerFactory(client, resyncPeriod) +// defer factory.WaitForStop() // Returns immediately if nothing was started. +// genericInformer := factory.ForResource(resource) +// typedInformer := factory.SomeAPIGroup().V1().SomeType() +// factory.Start(ctx.Done()) // Start processing these informers. +// synced := factory.WaitForCacheSync(ctx.Done()) +// for v, ok := range synced { +// if !ok { +// fmt.Fprintf(os.Stderr, "caches failed to sync: %v", v) +// return +// } +// } +// +// // Creating informers can also be created after Start, but then +// // Start must be called again: +// anotherGenericInformer := factory.ForResource(resource) +// factory.Start(ctx.Done()) +type SharedInformerFactory interface { + internalinterfaces.SharedInformerFactory + + // Start initializes all requested informers. They are handled in goroutines + // which run until the stop channel gets closed. + // Warning: Start does not block. When run in a go-routine, it will race with a later WaitForCacheSync. + Start(stopCh <-chan struct{}) + + // Shutdown marks a factory as shutting down. At that point no new + // informers can be started anymore and Start will return without + // doing anything. + // + // In addition, Shutdown blocks until all goroutines have terminated. For that + // to happen, the close channel(s) that they were started with must be closed, + // either before Shutdown gets called or while it is waiting. + // + // Shutdown may be called multiple times, even concurrently. All such calls will + // block until all goroutines have terminated. + Shutdown() + + // WaitForCacheSync blocks until all started informers' caches were synced + // or the stop channel gets closed. + WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + + // ForResource gives generic access to a shared informer of the matching type. + ForResource(resource schema.GroupVersionResource) (GenericInformer, error) + + // InformerFor returns the SharedIndexInformer for obj using an internal + // client. + InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer + + Samplecontroller() samplecontroller.Interface + Sonick8s() sonic.Interface +} + +func (f *sharedInformerFactory) Samplecontroller() samplecontroller.Interface { + return samplecontroller.New(f, f.namespace, f.tweakListOptions) +} + +func (f *sharedInformerFactory) Sonick8s() sonic.Interface { + return sonic.New(f, f.namespace, f.tweakListOptions) +} diff --git a/pkg/sonick8s/generated/informers/externalversions/generic.go b/pkg/sonick8s/generated/informers/externalversions/generic.go new file mode 100644 index 000000000..d86347c01 --- /dev/null +++ b/pkg/sonick8s/generated/informers/externalversions/generic.go @@ -0,0 +1,67 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package externalversions + +import ( + fmt "fmt" + + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" + v1alpha1 "k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1" + sonicv1alpha1 "k8s.io/sample-controller/pkg/apis/sonic/v1alpha1" +) + +// GenericInformer is type of SharedIndexInformer which will locate and delegate to other +// sharedInformers based on type +type GenericInformer interface { + Informer() cache.SharedIndexInformer + Lister() cache.GenericLister +} + +type genericInformer struct { + informer cache.SharedIndexInformer + resource schema.GroupResource +} + +// Informer returns the SharedIndexInformer. +func (f *genericInformer) Informer() cache.SharedIndexInformer { + return f.informer +} + +// Lister returns the GenericLister. +func (f *genericInformer) Lister() cache.GenericLister { + return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) +} + +// ForResource gives generic access to a shared informer of the matching type +// TODO extend this to unknown resources with a client pool +func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { + switch resource { + // Group=samplecontroller.k8s.io, Version=v1alpha1 + case v1alpha1.SchemeGroupVersion.WithResource("foos"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Samplecontroller().V1alpha1().Foos().Informer()}, nil + + // Group=sonick8s.io, Version=v1alpha1 + case sonicv1alpha1.SchemeGroupVersion.WithResource("networkdevices"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Sonick8s().V1alpha1().NetworkDevices().Informer()}, nil + + } + + return nil, fmt.Errorf("no informer found for %v", resource) +} diff --git a/pkg/sonick8s/generated/informers/externalversions/internalinterfaces/factory_interfaces.go b/pkg/sonick8s/generated/informers/externalversions/internalinterfaces/factory_interfaces.go new file mode 100644 index 000000000..5a8d3086b --- /dev/null +++ b/pkg/sonick8s/generated/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -0,0 +1,40 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package internalinterfaces + +import ( + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + cache "k8s.io/client-go/tools/cache" + versioned "k8s.io/sample-controller/pkg/sonick8s/generated/clientset/versioned" +) + +// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer. +type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer + +// SharedInformerFactory a small interface to allow for adding an informer without an import cycle +type SharedInformerFactory interface { + Start(stopCh <-chan struct{}) + InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer +} + +// TweakListOptionsFunc is a function that transforms a v1.ListOptions. +type TweakListOptionsFunc func(*v1.ListOptions) diff --git a/pkg/sonick8s/generated/informers/externalversions/samplecontroller/interface.go b/pkg/sonick8s/generated/informers/externalversions/samplecontroller/interface.go new file mode 100644 index 000000000..67a3ccc4c --- /dev/null +++ b/pkg/sonick8s/generated/informers/externalversions/samplecontroller/interface.go @@ -0,0 +1,46 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package samplecontroller + +import ( + internalinterfaces "k8s.io/sample-controller/pkg/sonick8s/generated/informers/externalversions/internalinterfaces" + v1alpha1 "k8s.io/sample-controller/pkg/sonick8s/generated/informers/externalversions/samplecontroller/v1alpha1" +) + +// Interface provides access to each of this group's versions. +type Interface interface { + // V1alpha1 provides access to shared informers for resources in V1alpha1. + V1alpha1() v1alpha1.Interface +} + +type group struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// V1alpha1 returns a new v1alpha1.Interface. +func (g *group) V1alpha1() v1alpha1.Interface { + return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/pkg/sonick8s/generated/informers/externalversions/samplecontroller/v1alpha1/foo.go b/pkg/sonick8s/generated/informers/externalversions/samplecontroller/v1alpha1/foo.go new file mode 100644 index 000000000..7de41a62c --- /dev/null +++ b/pkg/sonick8s/generated/informers/externalversions/samplecontroller/v1alpha1/foo.go @@ -0,0 +1,102 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + context "context" + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + apissamplecontrollerv1alpha1 "k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1" + versioned "k8s.io/sample-controller/pkg/sonick8s/generated/clientset/versioned" + internalinterfaces "k8s.io/sample-controller/pkg/sonick8s/generated/informers/externalversions/internalinterfaces" + samplecontrollerv1alpha1 "k8s.io/sample-controller/pkg/sonick8s/generated/listers/samplecontroller/v1alpha1" +) + +// FooInformer provides access to a shared informer and lister for +// Foos. +type FooInformer interface { + Informer() cache.SharedIndexInformer + Lister() samplecontrollerv1alpha1.FooLister +} + +type fooInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewFooInformer constructs a new informer for Foo type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFooInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredFooInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredFooInformer constructs a new informer for Foo type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredFooInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + cache.ToListWatcherWithWatchListSemantics(&cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SamplecontrollerV1alpha1().Foos(namespace).List(context.Background(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SamplecontrollerV1alpha1().Foos(namespace).Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SamplecontrollerV1alpha1().Foos(namespace).List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SamplecontrollerV1alpha1().Foos(namespace).Watch(ctx, options) + }, + }, client), + &apissamplecontrollerv1alpha1.Foo{}, + resyncPeriod, + indexers, + ) +} + +func (f *fooInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredFooInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *fooInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&apissamplecontrollerv1alpha1.Foo{}, f.defaultInformer) +} + +func (f *fooInformer) Lister() samplecontrollerv1alpha1.FooLister { + return samplecontrollerv1alpha1.NewFooLister(f.Informer().GetIndexer()) +} diff --git a/pkg/sonick8s/generated/informers/externalversions/samplecontroller/v1alpha1/interface.go b/pkg/sonick8s/generated/informers/externalversions/samplecontroller/v1alpha1/interface.go new file mode 100644 index 000000000..d7c46917b --- /dev/null +++ b/pkg/sonick8s/generated/informers/externalversions/samplecontroller/v1alpha1/interface.go @@ -0,0 +1,45 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + internalinterfaces "k8s.io/sample-controller/pkg/sonick8s/generated/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // Foos returns a FooInformer. + Foos() FooInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// Foos returns a FooInformer. +func (v *version) Foos() FooInformer { + return &fooInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/pkg/sonick8s/generated/informers/externalversions/sonic/interface.go b/pkg/sonick8s/generated/informers/externalversions/sonic/interface.go new file mode 100644 index 000000000..b8e59d116 --- /dev/null +++ b/pkg/sonick8s/generated/informers/externalversions/sonic/interface.go @@ -0,0 +1,46 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package sonic + +import ( + internalinterfaces "k8s.io/sample-controller/pkg/sonick8s/generated/informers/externalversions/internalinterfaces" + v1alpha1 "k8s.io/sample-controller/pkg/sonick8s/generated/informers/externalversions/sonic/v1alpha1" +) + +// Interface provides access to each of this group's versions. +type Interface interface { + // V1alpha1 provides access to shared informers for resources in V1alpha1. + V1alpha1() v1alpha1.Interface +} + +type group struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// V1alpha1 returns a new v1alpha1.Interface. +func (g *group) V1alpha1() v1alpha1.Interface { + return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/pkg/sonick8s/generated/informers/externalversions/sonic/v1alpha1/interface.go b/pkg/sonick8s/generated/informers/externalversions/sonic/v1alpha1/interface.go new file mode 100644 index 000000000..0fe7d1f25 --- /dev/null +++ b/pkg/sonick8s/generated/informers/externalversions/sonic/v1alpha1/interface.go @@ -0,0 +1,45 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + internalinterfaces "k8s.io/sample-controller/pkg/sonick8s/generated/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // NetworkDevices returns a NetworkDeviceInformer. + NetworkDevices() NetworkDeviceInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// NetworkDevices returns a NetworkDeviceInformer. +func (v *version) NetworkDevices() NetworkDeviceInformer { + return &networkDeviceInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/pkg/sonick8s/generated/informers/externalversions/sonic/v1alpha1/networkdevice.go b/pkg/sonick8s/generated/informers/externalversions/sonic/v1alpha1/networkdevice.go new file mode 100644 index 000000000..93f186917 --- /dev/null +++ b/pkg/sonick8s/generated/informers/externalversions/sonic/v1alpha1/networkdevice.go @@ -0,0 +1,102 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + context "context" + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + apissonicv1alpha1 "k8s.io/sample-controller/pkg/apis/sonic/v1alpha1" + versioned "k8s.io/sample-controller/pkg/sonick8s/generated/clientset/versioned" + internalinterfaces "k8s.io/sample-controller/pkg/sonick8s/generated/informers/externalversions/internalinterfaces" + sonicv1alpha1 "k8s.io/sample-controller/pkg/sonick8s/generated/listers/sonic/v1alpha1" +) + +// NetworkDeviceInformer provides access to a shared informer and lister for +// NetworkDevices. +type NetworkDeviceInformer interface { + Informer() cache.SharedIndexInformer + Lister() sonicv1alpha1.NetworkDeviceLister +} + +type networkDeviceInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewNetworkDeviceInformer constructs a new informer for NetworkDevice type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewNetworkDeviceInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredNetworkDeviceInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredNetworkDeviceInformer constructs a new informer for NetworkDevice type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredNetworkDeviceInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + cache.ToListWatcherWithWatchListSemantics(&cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.Sonick8sV1alpha1().NetworkDevices(namespace).List(context.Background(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.Sonick8sV1alpha1().NetworkDevices(namespace).Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.Sonick8sV1alpha1().NetworkDevices(namespace).List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.Sonick8sV1alpha1().NetworkDevices(namespace).Watch(ctx, options) + }, + }, client), + &apissonicv1alpha1.NetworkDevice{}, + resyncPeriod, + indexers, + ) +} + +func (f *networkDeviceInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredNetworkDeviceInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *networkDeviceInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&apissonicv1alpha1.NetworkDevice{}, f.defaultInformer) +} + +func (f *networkDeviceInformer) Lister() sonicv1alpha1.NetworkDeviceLister { + return sonicv1alpha1.NewNetworkDeviceLister(f.Informer().GetIndexer()) +} diff --git a/pkg/sonick8s/generated/listers/samplecontroller/v1alpha1/expansion_generated.go b/pkg/sonick8s/generated/listers/samplecontroller/v1alpha1/expansion_generated.go new file mode 100644 index 000000000..9a34636b0 --- /dev/null +++ b/pkg/sonick8s/generated/listers/samplecontroller/v1alpha1/expansion_generated.go @@ -0,0 +1,27 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +// FooListerExpansion allows custom methods to be added to +// FooLister. +type FooListerExpansion interface{} + +// FooNamespaceListerExpansion allows custom methods to be added to +// FooNamespaceLister. +type FooNamespaceListerExpansion interface{} diff --git a/pkg/sonick8s/generated/listers/samplecontroller/v1alpha1/foo.go b/pkg/sonick8s/generated/listers/samplecontroller/v1alpha1/foo.go new file mode 100644 index 000000000..cbe948fe3 --- /dev/null +++ b/pkg/sonick8s/generated/listers/samplecontroller/v1alpha1/foo.go @@ -0,0 +1,70 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + labels "k8s.io/apimachinery/pkg/labels" + listers "k8s.io/client-go/listers" + cache "k8s.io/client-go/tools/cache" + samplecontrollerv1alpha1 "k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1" +) + +// FooLister helps list Foos. +// All objects returned here must be treated as read-only. +type FooLister interface { + // List lists all Foos in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*samplecontrollerv1alpha1.Foo, err error) + // Foos returns an object that can list and get Foos. + Foos(namespace string) FooNamespaceLister + FooListerExpansion +} + +// fooLister implements the FooLister interface. +type fooLister struct { + listers.ResourceIndexer[*samplecontrollerv1alpha1.Foo] +} + +// NewFooLister returns a new FooLister. +func NewFooLister(indexer cache.Indexer) FooLister { + return &fooLister{listers.New[*samplecontrollerv1alpha1.Foo](indexer, samplecontrollerv1alpha1.Resource("foo"))} +} + +// Foos returns an object that can list and get Foos. +func (s *fooLister) Foos(namespace string) FooNamespaceLister { + return fooNamespaceLister{listers.NewNamespaced[*samplecontrollerv1alpha1.Foo](s.ResourceIndexer, namespace)} +} + +// FooNamespaceLister helps list and get Foos. +// All objects returned here must be treated as read-only. +type FooNamespaceLister interface { + // List lists all Foos in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*samplecontrollerv1alpha1.Foo, err error) + // Get retrieves the Foo from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*samplecontrollerv1alpha1.Foo, error) + FooNamespaceListerExpansion +} + +// fooNamespaceLister implements the FooNamespaceLister +// interface. +type fooNamespaceLister struct { + listers.ResourceIndexer[*samplecontrollerv1alpha1.Foo] +} diff --git a/pkg/sonick8s/generated/listers/sonic/v1alpha1/expansion_generated.go b/pkg/sonick8s/generated/listers/sonic/v1alpha1/expansion_generated.go new file mode 100644 index 000000000..335a9e61a --- /dev/null +++ b/pkg/sonick8s/generated/listers/sonic/v1alpha1/expansion_generated.go @@ -0,0 +1,27 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +// NetworkDeviceListerExpansion allows custom methods to be added to +// NetworkDeviceLister. +type NetworkDeviceListerExpansion interface{} + +// NetworkDeviceNamespaceListerExpansion allows custom methods to be added to +// NetworkDeviceNamespaceLister. +type NetworkDeviceNamespaceListerExpansion interface{} diff --git a/pkg/sonick8s/generated/listers/sonic/v1alpha1/networkdevice.go b/pkg/sonick8s/generated/listers/sonic/v1alpha1/networkdevice.go new file mode 100644 index 000000000..f862c6859 --- /dev/null +++ b/pkg/sonick8s/generated/listers/sonic/v1alpha1/networkdevice.go @@ -0,0 +1,70 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + labels "k8s.io/apimachinery/pkg/labels" + listers "k8s.io/client-go/listers" + cache "k8s.io/client-go/tools/cache" + sonicv1alpha1 "k8s.io/sample-controller/pkg/apis/sonic/v1alpha1" +) + +// NetworkDeviceLister helps list NetworkDevices. +// All objects returned here must be treated as read-only. +type NetworkDeviceLister interface { + // List lists all NetworkDevices in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*sonicv1alpha1.NetworkDevice, err error) + // NetworkDevices returns an object that can list and get NetworkDevices. + NetworkDevices(namespace string) NetworkDeviceNamespaceLister + NetworkDeviceListerExpansion +} + +// networkDeviceLister implements the NetworkDeviceLister interface. +type networkDeviceLister struct { + listers.ResourceIndexer[*sonicv1alpha1.NetworkDevice] +} + +// NewNetworkDeviceLister returns a new NetworkDeviceLister. +func NewNetworkDeviceLister(indexer cache.Indexer) NetworkDeviceLister { + return &networkDeviceLister{listers.New[*sonicv1alpha1.NetworkDevice](indexer, sonicv1alpha1.Resource("networkdevice"))} +} + +// NetworkDevices returns an object that can list and get NetworkDevices. +func (s *networkDeviceLister) NetworkDevices(namespace string) NetworkDeviceNamespaceLister { + return networkDeviceNamespaceLister{listers.NewNamespaced[*sonicv1alpha1.NetworkDevice](s.ResourceIndexer, namespace)} +} + +// NetworkDeviceNamespaceLister helps list and get NetworkDevices. +// All objects returned here must be treated as read-only. +type NetworkDeviceNamespaceLister interface { + // List lists all NetworkDevices in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*sonicv1alpha1.NetworkDevice, err error) + // Get retrieves the NetworkDevice from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*sonicv1alpha1.NetworkDevice, error) + NetworkDeviceNamespaceListerExpansion +} + +// networkDeviceNamespaceLister implements the NetworkDeviceNamespaceLister +// interface. +type networkDeviceNamespaceLister struct { + listers.ResourceIndexer[*sonicv1alpha1.NetworkDevice] +} From b1a9a1329c93f3f7629c0e5a5a7d9f60aa728a35 Mon Sep 17 00:00:00 2001 From: LOngquan Sha Date: Tue, 28 Oct 2025 08:32:05 +0000 Subject: [PATCH 3/5] update --- config/crd/admin.conf | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 config/crd/admin.conf diff --git a/config/crd/admin.conf b/config/crd/admin.conf deleted file mode 100644 index e69de29bb..000000000 From f48f951ed196c5fb7cee5288c8146ad8e99869cd Mon Sep 17 00:00:00 2001 From: LOngquan Sha Date: Tue, 28 Oct 2025 08:42:06 +0000 Subject: [PATCH 4/5] update --- config/crd/device_example.yaml | 21 --------------------- pkg/controller/networkdevice_controller.go | 10 ++++++++++ 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/config/crd/device_example.yaml b/config/crd/device_example.yaml index ff2f7db33..ef9d10744 100644 --- a/config/crd/device_example.yaml +++ b/config/crd/device_example.yaml @@ -7,24 +7,3 @@ spec: os: os-type: "SONiC" version: "202305" -status: - state: "Healthy" - lastTransitionTime: "2025-10-28T12:00:00Z" - os: - os-type: "SONiC" - version: "202305" - operation: - id: "op-123" - name: "Upgrade" - status: "Completed" - operationAction: - id: "action-1" - name: "Install" - status: "Success" - conditions: - - type: "Ready" - status: "True" - lastProbeTime: "2025-10-28T12:00:00Z" - lastTransitionTime: "2025-10-28T12:00:00Z" - reason: "AllSystemsGo" - message: "Device is ready" \ No newline at end of file diff --git a/pkg/controller/networkdevice_controller.go b/pkg/controller/networkdevice_controller.go index 520ba1b64..59fe79d01 100644 --- a/pkg/controller/networkdevice_controller.go +++ b/pkg/controller/networkdevice_controller.go @@ -233,6 +233,16 @@ func (c *Controller) syncHandler(ctx context.Context, objectRef cache.ObjectName return err } + // if the status is nil, initialize it + if device.Status.State == "" { + device.Status = samplev1alpha1.NetworkDeviceStatus{ + State: "Healthy", + } + c.updateNetworkDeviceStatus(ctx, device) + logger.Info("Initialized NetworkDevice status", "deviceStatus", device.Status) + return nil + } + // if device has no status or no operation, nothing to do if device.Status.Operation == nil { logger.Info("NetworkDevice has no operation defined, skipping processing") From f3d912c9cbbfa1327a7bbd26a032299a8988d5b6 Mon Sep 17 00:00:00 2001 From: LOngquan Sha Date: Tue, 28 Oct 2025 09:44:17 +0000 Subject: [PATCH 5/5] update --- pkg/controller/networkdevice_controller.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/pkg/controller/networkdevice_controller.go b/pkg/controller/networkdevice_controller.go index 59fe79d01..a6b818a78 100644 --- a/pkg/controller/networkdevice_controller.go +++ b/pkg/controller/networkdevice_controller.go @@ -48,23 +48,23 @@ import ( const controllerAgentName = "networkdevice-controller" const ( - // SuccessSynced is used as part of the Event 'reason' when a Foo is synced + // SuccessSynced is used as part of the Event 'reason' when a NetworkDevice is synced SuccessSynced = "Synced" - // ErrResourceExists is used as part of the Event 'reason' when a Foo fails + // ErrResourceExists is used as part of the Event 'reason' when a NetworkDevice fails // to sync due to a Deployment of the same name already existing. ErrResourceExists = "ErrResourceExists" // MessageResourceExists is the message used for Events when a resource // fails to sync due to a Deployment already existing - MessageResourceExists = "Resource %q already exists and is not managed by Foo" - // MessageResourceSynced is the message used for an Event fired when a Foo + MessageResourceExists = "Resource %q already exists and is not managed by NetworkDevice" + // MessageResourceSynced is the message used for an Event fired when a NetworkDevice // is synced successfully - MessageResourceSynced = "Foo synced successfully" + MessageResourceSynced = "NetworkDevice synced successfully" // FieldManager distinguishes this controller from other things writing to API objects FieldManager = controllerAgentName ) -// Controller is the controller implementation for Foo resources +// Controller is the controller implementation for NetworkDevice resources type Controller struct { // kubeclientset is a standard kubernetes clientset kubeclientset kubernetes.Interface @@ -144,7 +144,7 @@ func (c *Controller) Run(ctx context.Context, workers int) error { logger := klog.FromContext(ctx) // Start the informer factories to begin populating the informer caches - logger.Info("Starting Foo controller") + logger.Info("Starting NetworkDevice controller") // Wait for the caches to be synced before starting workers logger.Info("Waiting for informer caches to sync") @@ -154,7 +154,7 @@ func (c *Controller) Run(ctx context.Context, workers int) error { } logger.Info("Starting workers", "count", workers) - // Launch two workers to process Foo resources + // Launch two workers to process NetworkDevice resources for i := 0; i < workers; i++ { go wait.UntilWithContext(ctx, c.runWorker, time.Second) } @@ -215,7 +215,7 @@ func (c *Controller) processNextWorkItem(ctx context.Context) bool { } // syncHandler compares the actual state with the desired, and attempts to -// converge the two. It then updates the Status block of the Foo resource +// converge the two. It then updates the Status block of the NetworkDevice resource // with the current status of the resource. func (c *Controller) syncHandler(ctx context.Context, objectRef cache.ObjectName) error { logger := klog.LoggerWithValues(klog.FromContext(ctx), "objectRef", objectRef) @@ -345,9 +345,9 @@ func (c *Controller) handleObject(obj interface{}) { } logger.V(4).Info("Processing object", "object", klog.KObj(object)) if ownerRef := metav1.GetControllerOf(object); ownerRef != nil { - // If this object is not owned by a Foo, we should not do anything more + // If this object is not owned by a NetworkDevice, we should not do anything more // with it. - if ownerRef.Kind != "Foo" { + if ownerRef.Kind != "NetworkDevice" { return }