From cf777c2e53d59a06d1a459733090c4919dfd13ff Mon Sep 17 00:00:00 2001 From: Huifeng Le Date: Thu, 14 Jan 2021 15:24:15 +0800 Subject: [PATCH] CNFStatus CRD Controller Add CNFStatus CRD controller to query CNF status periodically Signed-off-by: Huifeng Le Change-Id: I86a7fca4fd9248a22cadda30babde4346ea29bd8 Signed-off-by: Huifeng Le Change-Id: Ie5ed1f5d5ad87c367ad0a3342105515a44725558 Signed-off-by: Huifeng Le --- platform/crd-ctrlr/examples/sdewan-controller.yaml | 76 +++++++++++ platform/crd-ctrlr/src/PROJECT | 3 + .../crd-ctrlr/src/api/v1alpha1/cnfstatus_types.go | 76 +++++++++++ .../src/api/v1alpha1/zz_generated.deepcopy.go | 113 ++++++++++++++++ .../batch.sdewan.akraino.org_cnfstatuses.yaml | 84 ++++++++++++ .../crd-ctrlr/src/config/crd/kustomization.yaml | 3 + .../crd/patches/cainjection_in_cnfstatuses.yaml | 8 ++ .../config/crd/patches/webhook_in_cnfstatuses.yaml | 17 +++ .../src/config/rbac/cnfstatus_editor_role.yaml | 24 ++++ .../src/config/rbac/cnfstatus_viewer_role.yaml | 20 +++ .../config/samples/batch_v1alpha1_cnfstatus.yaml | 6 + .../src/controllers/cnfstatus_controller.go | 148 +++++++++++++++++++++ platform/crd-ctrlr/src/main.go | 14 ++ platform/crd-ctrlr/src/openwrt/status.go | 55 ++++++++ 14 files changed, 647 insertions(+) create mode 100644 platform/crd-ctrlr/src/api/v1alpha1/cnfstatus_types.go create mode 100644 platform/crd-ctrlr/src/config/crd/bases/batch.sdewan.akraino.org_cnfstatuses.yaml create mode 100644 platform/crd-ctrlr/src/config/crd/patches/cainjection_in_cnfstatuses.yaml create mode 100644 platform/crd-ctrlr/src/config/crd/patches/webhook_in_cnfstatuses.yaml create mode 100644 platform/crd-ctrlr/src/config/rbac/cnfstatus_editor_role.yaml create mode 100644 platform/crd-ctrlr/src/config/rbac/cnfstatus_viewer_role.yaml create mode 100644 platform/crd-ctrlr/src/config/samples/batch_v1alpha1_cnfstatus.yaml create mode 100644 platform/crd-ctrlr/src/controllers/cnfstatus_controller.go create mode 100644 platform/crd-ctrlr/src/openwrt/status.go diff --git a/platform/crd-ctrlr/examples/sdewan-controller.yaml b/platform/crd-ctrlr/examples/sdewan-controller.yaml index 174e1b4..48edbb1 100644 --- a/platform/crd-ctrlr/examples/sdewan-controller.yaml +++ b/platform/crd-ctrlr/examples/sdewan-controller.yaml @@ -75,6 +75,82 @@ status: --- apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.2.5 + creationTimestamp: null + name: cnfstatuses.batch.sdewan.akraino.org +spec: + group: batch.sdewan.akraino.org + names: + kind: CNFStatus + listKind: CNFStatusList + plural: cnfstatuses + singular: cnfstatus + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + description: CNFStatus is the Schema for the cnfstatuses API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: CNFStatusSpec defines the desired state of CNFStatus + type: object + status: + description: CNFStatusStatus defines the observed state of CNFStatus + properties: + appliedGeneration: + description: 'INSERT ADDITIONAL STATUS FIELD - define observed state of cluster Important: Run "make" to regenerate code after modifying this file' + format: int64 + type: integer + appliedTime: + format: date-time + type: string + information: + items: + description: CNFStatusInformation defines the runtime information of a CMF + properties: + ip: + type: string + name: + type: string + namespace: + type: string + node: + type: string + purpose: + type: string + status: + type: string + required: + - name + type: object + type: array + type: object + type: object + version: v1alpha1 + versions: + - name: v1alpha1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.2.5 diff --git a/platform/crd-ctrlr/src/PROJECT b/platform/crd-ctrlr/src/PROJECT index 7c4a411..26c2994 100644 --- a/platform/crd-ctrlr/src/PROJECT +++ b/platform/crd-ctrlr/src/PROJECT @@ -37,4 +37,7 @@ resources: - group: batch kind: SdewanApplication version: v1alpha1 +- group: batch + kind: CNFStatus + version: v1alpha1 version: "2" diff --git a/platform/crd-ctrlr/src/api/v1alpha1/cnfstatus_types.go b/platform/crd-ctrlr/src/api/v1alpha1/cnfstatus_types.go new file mode 100644 index 0000000..927b527 --- /dev/null +++ b/platform/crd-ctrlr/src/api/v1alpha1/cnfstatus_types.go @@ -0,0 +1,76 @@ +/* + +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" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// CNFStatusSpec defines the desired state of CNFStatus +type CNFStatusSpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "make" to regenerate code after modifying this file +} + +// CNFStatusInformation defines the runtime information of a CMF +type CNFStatusInformation struct { + Name string `json:"name"` + NameSpace string `json:"namespace,omitempty"` + Node string `json:"node,omitempty"` + Purpose string `json:"purpose,omitempty"` + IP string `json:"ip,omitempty"` + Status string `json:"status,omitempty"` +} + +// CNFStatusStatus defines the observed state of CNFStatus +type CNFStatusStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file + // +optional + AppliedGeneration int64 `json:"appliedGeneration,omitempty"` + // +optional + AppliedTime *metav1.Time `json:"appliedTime,omitempty"` + // +optional + Information []CNFStatusInformation `json:"information,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status + +// CNFStatus is the Schema for the cnfstatuses API +type CNFStatus struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec CNFStatusSpec `json:"spec,omitempty"` + Status CNFStatusStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// CNFStatusList contains a list of CNFStatus +type CNFStatusList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []CNFStatus `json:"items"` +} + +func init() { + SchemeBuilder.Register(&CNFStatus{}, &CNFStatusList{}) +} diff --git a/platform/crd-ctrlr/src/api/v1alpha1/zz_generated.deepcopy.go b/platform/crd-ctrlr/src/api/v1alpha1/zz_generated.deepcopy.go index ed719e7..9a21a7a 100644 --- a/platform/crd-ctrlr/src/api/v1alpha1/zz_generated.deepcopy.go +++ b/platform/crd-ctrlr/src/api/v1alpha1/zz_generated.deepcopy.go @@ -142,6 +142,119 @@ func (in *CNFServiceSpec) DeepCopy() *CNFServiceSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CNFStatus) DeepCopyInto(out *CNFStatus) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CNFStatus. +func (in *CNFStatus) DeepCopy() *CNFStatus { + if in == nil { + return nil + } + out := new(CNFStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *CNFStatus) 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 *CNFStatusInformation) DeepCopyInto(out *CNFStatusInformation) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CNFStatusInformation. +func (in *CNFStatusInformation) DeepCopy() *CNFStatusInformation { + if in == nil { + return nil + } + out := new(CNFStatusInformation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CNFStatusList) DeepCopyInto(out *CNFStatusList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]CNFStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CNFStatusList. +func (in *CNFStatusList) DeepCopy() *CNFStatusList { + if in == nil { + return nil + } + out := new(CNFStatusList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *CNFStatusList) 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 *CNFStatusSpec) DeepCopyInto(out *CNFStatusSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CNFStatusSpec. +func (in *CNFStatusSpec) DeepCopy() *CNFStatusSpec { + if in == nil { + return nil + } + out := new(CNFStatusSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CNFStatusStatus) DeepCopyInto(out *CNFStatusStatus) { + *out = *in + if in.AppliedTime != nil { + in, out := &in.AppliedTime, &out.AppliedTime + *out = (*in).DeepCopy() + } + if in.Information != nil { + in, out := &in.Information, &out.Information + *out = make([]CNFStatusInformation, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CNFStatusStatus. +func (in *CNFStatusStatus) DeepCopy() *CNFStatusStatus { + if in == nil { + return nil + } + out := new(CNFStatusStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Connection) DeepCopyInto(out *Connection) { *out = *in diff --git a/platform/crd-ctrlr/src/config/crd/bases/batch.sdewan.akraino.org_cnfstatuses.yaml b/platform/crd-ctrlr/src/config/crd/bases/batch.sdewan.akraino.org_cnfstatuses.yaml new file mode 100644 index 0000000..2a24a62 --- /dev/null +++ b/platform/crd-ctrlr/src/config/crd/bases/batch.sdewan.akraino.org_cnfstatuses.yaml @@ -0,0 +1,84 @@ + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.2.5 + creationTimestamp: null + name: cnfstatuses.batch.sdewan.akraino.org +spec: + group: batch.sdewan.akraino.org + names: + kind: CNFStatus + listKind: CNFStatusList + plural: cnfstatuses + singular: cnfstatus + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + description: CNFStatus is the Schema for the cnfstatuses API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: CNFStatusSpec defines the desired state of CNFStatus + type: object + status: + description: CNFStatusStatus defines the observed state of CNFStatus + properties: + appliedGeneration: + description: 'INSERT ADDITIONAL STATUS FIELD - define observed state + of cluster Important: Run "make" to regenerate code after modifying + this file' + format: int64 + type: integer + appliedTime: + format: date-time + type: string + information: + items: + description: CNFStatusInformation defines the runtime information + of a CMF + properties: + ip: + type: string + name: + type: string + namespace: + type: string + node: + type: string + purpose: + type: string + status: + type: string + required: + - name + type: object + type: array + type: object + type: object + version: v1alpha1 + versions: + - name: v1alpha1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/platform/crd-ctrlr/src/config/crd/kustomization.yaml b/platform/crd-ctrlr/src/config/crd/kustomization.yaml index 279ef89..54a6b47 100644 --- a/platform/crd-ctrlr/src/config/crd/kustomization.yaml +++ b/platform/crd-ctrlr/src/config/crd/kustomization.yaml @@ -14,6 +14,7 @@ resources: - bases/batch.sdewan.akraino.org_ipsecsites.yaml - bases/batch.sdewan.akraino.org_cnfservices.yaml - bases/batch.sdewan.akraino.org_sdewanapplications.yaml +- bases/batch.sdewan.akraino.org_cnfstatuses.yaml # +kubebuilder:scaffold:crdkustomizeresource patchesStrategicMerge: @@ -31,6 +32,7 @@ patchesStrategicMerge: #- patches/webhook_in_ipsecsites.yaml #- patches/webhook_in_cnfservices.yaml #- patches/webhook_in_sdewanapplications.yaml +#- patches/webhook_in_cnfstatuses.yaml # +kubebuilder:scaffold:crdkustomizewebhookpatch # [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix. @@ -47,6 +49,7 @@ patchesStrategicMerge: #- patches/cainjection_in_ipsecsites.yaml #- patches/cainjection_in_cnfservices.yaml #- patches/cainjection_in_sdewanapplications.yaml +#- patches/cainjection_in_cnfstatuses.yaml # +kubebuilder:scaffold:crdkustomizecainjectionpatch # the following config is for teaching kustomize how to do kustomization for CRDs. diff --git a/platform/crd-ctrlr/src/config/crd/patches/cainjection_in_cnfstatuses.yaml b/platform/crd-ctrlr/src/config/crd/patches/cainjection_in_cnfstatuses.yaml new file mode 100644 index 0000000..5a10441 --- /dev/null +++ b/platform/crd-ctrlr/src/config/crd/patches/cainjection_in_cnfstatuses.yaml @@ -0,0 +1,8 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +# CRD conversion requires k8s 1.13 or later. +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) + name: cnfstatuses.batch.sdewan.akraino.org diff --git a/platform/crd-ctrlr/src/config/crd/patches/webhook_in_cnfstatuses.yaml b/platform/crd-ctrlr/src/config/crd/patches/webhook_in_cnfstatuses.yaml new file mode 100644 index 0000000..ba8d604 --- /dev/null +++ b/platform/crd-ctrlr/src/config/crd/patches/webhook_in_cnfstatuses.yaml @@ -0,0 +1,17 @@ +# The following patch enables conversion webhook for CRD +# CRD conversion requires k8s 1.13 or later. +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: cnfstatuses.batch.sdewan.akraino.org +spec: + conversion: + strategy: Webhook + webhookClientConfig: + # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, + # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) + caBundle: Cg== + service: + namespace: system + name: webhook-service + path: /convert diff --git a/platform/crd-ctrlr/src/config/rbac/cnfstatus_editor_role.yaml b/platform/crd-ctrlr/src/config/rbac/cnfstatus_editor_role.yaml new file mode 100644 index 0000000..2449136 --- /dev/null +++ b/platform/crd-ctrlr/src/config/rbac/cnfstatus_editor_role.yaml @@ -0,0 +1,24 @@ +# permissions for end users to edit cnfstatuses. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: cnfstatus-editor-role +rules: +- apiGroups: + - batch.sdewan.akraino.org + resources: + - cnfstatuses + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - batch.sdewan.akraino.org + resources: + - cnfstatuses/status + verbs: + - get diff --git a/platform/crd-ctrlr/src/config/rbac/cnfstatus_viewer_role.yaml b/platform/crd-ctrlr/src/config/rbac/cnfstatus_viewer_role.yaml new file mode 100644 index 0000000..5d1b5b6 --- /dev/null +++ b/platform/crd-ctrlr/src/config/rbac/cnfstatus_viewer_role.yaml @@ -0,0 +1,20 @@ +# permissions for end users to view cnfstatuses. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: cnfstatus-viewer-role +rules: +- apiGroups: + - batch.sdewan.akraino.org + resources: + - cnfstatuses + verbs: + - get + - list + - watch +- apiGroups: + - batch.sdewan.akraino.org + resources: + - cnfstatuses/status + verbs: + - get diff --git a/platform/crd-ctrlr/src/config/samples/batch_v1alpha1_cnfstatus.yaml b/platform/crd-ctrlr/src/config/samples/batch_v1alpha1_cnfstatus.yaml new file mode 100644 index 0000000..3c93896 --- /dev/null +++ b/platform/crd-ctrlr/src/config/samples/batch_v1alpha1_cnfstatus.yaml @@ -0,0 +1,6 @@ +apiVersion: batch.sdewan.akraino.org/v1alpha1 +kind: CNFStatus +metadata: + name: cnfstatus-sample +spec: + # Add fields here diff --git a/platform/crd-ctrlr/src/controllers/cnfstatus_controller.go b/platform/crd-ctrlr/src/controllers/cnfstatus_controller.go new file mode 100644 index 0000000..eb20943 --- /dev/null +++ b/platform/crd-ctrlr/src/controllers/cnfstatus_controller.go @@ -0,0 +1,148 @@ +/* + +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 controllers + +import ( + "context" + "encoding/json" + "github.com/go-logr/logr" + "time" + + corev1 "k8s.io/api/core/v1" + errs "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" + batchv1alpha1 "sdewan.akraino.org/sdewan/api/v1alpha1" + "sdewan.akraino.org/sdewan/openwrt" + "sigs.k8s.io/controller-runtime/pkg/client" + "sync" +) + +var cnfCRNameSpace = "sdewan-system" +var cnfCRName = "cnf-status" +var inQueryStatus = false + +// SdewanCNFStatusController: query CNF status periodically +type SdewanCNFStatusController struct { + client.Client + Log logr.Logger + CheckInterval time.Duration + mux sync.Mutex +} + +func (r *SdewanCNFStatusController) SetupWithManager() error { + go wait.Until(r.SafeQuery, r.CheckInterval, wait.NeverStop) + + return nil +} + +func (r *SdewanCNFStatusController) GetInstance(ctx context.Context) (*batchv1alpha1.CNFStatus, error) { + instance := &batchv1alpha1.CNFStatus{} + err := r.Get(ctx, client.ObjectKey{ + Namespace: cnfCRNameSpace, + Name: cnfCRName, + }, instance) + + if errs.IsNotFound(err) { + // No instance, create the instance + r.Log.Info("Create New CNFStatus CR") + instance = &batchv1alpha1.CNFStatus{ + ObjectMeta: metav1.ObjectMeta{ + Name: cnfCRName, + Namespace: cnfCRNameSpace, + }, + Spec: batchv1alpha1.CNFStatusSpec{}, + } + + err = r.Create(ctx, instance) + if err != nil { + return &batchv1alpha1.CNFStatus{}, err + } + } + + return instance, nil +} + +// Query CNFStatus information +func (r *SdewanCNFStatusController) SafeQuery() { + doQuery := true + r.mux.Lock() + if inQueryStatus == false { + inQueryStatus = true + } else { + doQuery = false + } + r.mux.Unlock() + + if doQuery { + r.query() + + r.mux.Lock() + inQueryStatus = false + r.mux.Unlock() + } +} + +func (r *SdewanCNFStatusController) query() { + ctx := context.Background() + + instance, err := r.GetInstance(ctx) + if err != nil { + r.Log.Info(err.Error()) + } else { + r.Log.Info("Query CNFStatus CR Instance: " + instance.ObjectMeta.Name) + } + + // Set Status infomration + instance.Status.AppliedGeneration = instance.Generation + instance.Status.AppliedTime = &metav1.Time{Time: time.Now()} + instance.Status.Information = []batchv1alpha1.CNFStatusInformation{} + + cnfPodList := &corev1.PodList{} + err = r.List(ctx, cnfPodList, client.HasLabels{"sdewanPurpose"}) + if err != nil { + r.Log.Info(err.Error()) + return + } + + for _, cnfPod := range cnfPodList.Items { + info := &batchv1alpha1.CNFStatusInformation{} + info.Name = cnfPod.ObjectMeta.Name + info.NameSpace = cnfPod.ObjectMeta.Namespace + info.Node = cnfPod.Spec.NodeName + info.Purpose = cnfPod.ObjectMeta.Labels["sdewanPurpose"] + info.IP = cnfPod.Status.PodIP + + // Get CNF Status + clientInfo := &openwrt.OpenwrtClientInfo{Ip: info.IP, User: "root", Password: ""} + openwrtClient := openwrt.GetOpenwrtClient(*clientInfo) + status_client := openwrt.StatusClient{OpenwrtClient: openwrtClient} + cnf_status, err := status_client.GetStatus() + if err != nil { + info.Status = "Not Available" + } else { + p_data, _ := json.Marshal(cnf_status) + info.Status = string(p_data) + } + instance.Status.Information = append(instance.Status.Information, *info) + } + + // Update the CNFStatus CR + err = r.Status().Update(ctx, instance) + if err != nil { + r.Log.Info(err.Error()) + } +} diff --git a/platform/crd-ctrlr/src/main.go b/platform/crd-ctrlr/src/main.go index c50c83d..beb3dee 100644 --- a/platform/crd-ctrlr/src/main.go +++ b/platform/crd-ctrlr/src/main.go @@ -20,6 +20,7 @@ import ( "flag" "fmt" "os" + "time" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" @@ -50,9 +51,12 @@ func init() { func main() { var metricsAddr string var enableLeaderElection bool + var checkInterval int flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.") flag.BoolVar(&enableLeaderElection, "enable-leader-election", false, "Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager.") + flag.IntVar(&checkInterval, "check-interval", 30, + "The check interval for query of CNF Status (seconds)") flag.Parse() ctrl.SetLogger(zap.New(func(o *zap.Options) { @@ -227,6 +231,16 @@ func main() { } // +kubebuilder:scaffold:builder + setupLog.Info("start CNFStatusController to query CNF status periodicly") + if err = (&controllers.SdewanCNFStatusController{ + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("SdewanCNFStatus"), + CheckInterval: time.Duration(checkInterval) * time.Second, + }).SetupWithManager(); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "SdewanCNFStatus") + os.Exit(1) + } + setupLog.Info("starting manager") if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { setupLog.Error(err, "problem running manager") diff --git a/platform/crd-ctrlr/src/openwrt/status.go b/platform/crd-ctrlr/src/openwrt/status.go new file mode 100644 index 0000000..5c4b59e --- /dev/null +++ b/platform/crd-ctrlr/src/openwrt/status.go @@ -0,0 +1,55 @@ +package openwrt + +import ( + "encoding/json" +) + +const ( + statusBaseURL = "sdewan/v1/" +) + +type StatusClient struct { + OpenwrtClient *openwrtClient +} + +// Status Info +type SdewanModuleStatus struct { + Name string `json:"name"` + Status interface{} `json:"status"` +} + +func (o *SdewanModuleStatus) GetName() string { + return o.Name +} + +// Status APIs +// get status +func (m *StatusClient) GetStatus() (*[]SdewanModuleStatus, error) { + response, err := m.OpenwrtClient.Get(statusBaseURL + "status") + if err != nil { + return nil, err + } + + var sdewanStatus []SdewanModuleStatus + err = json.Unmarshal([]byte(response), &sdewanStatus) + if err != nil { + return nil, err + } + + return &sdewanStatus, nil +} + +func (m *StatusClient) GetModuleStatus(mname string) (*SdewanModuleStatus, error) { + response, err := m.OpenwrtClient.Get(statusBaseURL + "status/" + mname) + if err != nil { + return nil, err + } + + var sdewanModuleStatus SdewanModuleStatus + err = json.Unmarshal([]byte(response), &sdewanModuleStatus) + if err != nil { + return nil, err + } + + return &sdewanModuleStatus, nil +} -- 2.16.6