Implement Route CR controller 54/4054/3
authorLe Yao <le.yao@intel.com>
Fri, 15 Jan 2021 07:32:23 +0000 (07:32 +0000)
committerLe Yao <le.yao@intel.com>
Fri, 29 Jan 2021 02:20:44 +0000 (02:20 +0000)
The Route CR controller handles the Route resource and call CNF Route
RESTful API to add/update/delete/get the route rule.

Signed-off-by: Le Yao <le.yao@intel.com>
Change-Id: I95871e1e95ccacf5790697d2e5105448f630aac2

16 files changed:
platform/crd-ctrlr/examples/sdewan-controller.yaml
platform/crd-ctrlr/src/PROJECT
platform/crd-ctrlr/src/api/v1alpha1/cnfroute_types.go [new file with mode: 0644]
platform/crd-ctrlr/src/api/v1alpha1/zz_generated.deepcopy.go
platform/crd-ctrlr/src/config/crd/bases/batch.sdewan.akraino.org_cnfroutes.yaml [new file with mode: 0644]
platform/crd-ctrlr/src/config/crd/kustomization.yaml
platform/crd-ctrlr/src/config/crd/patches/cainjection_in_cnfroutes.yaml [new file with mode: 0644]
platform/crd-ctrlr/src/config/crd/patches/webhook_in_cnfroutes.yaml [new file with mode: 0644]
platform/crd-ctrlr/src/config/rbac/cnfroute_editor_role.yaml [new file with mode: 0644]
platform/crd-ctrlr/src/config/rbac/cnfroute_viewer_role.yaml [new file with mode: 0644]
platform/crd-ctrlr/src/config/rbac/role.yaml
platform/crd-ctrlr/src/config/samples/batch_v1alpha1_cnfroute.yaml [new file with mode: 0644]
platform/crd-ctrlr/src/controllers/cnfroute_controller.go [new file with mode: 0644]
platform/crd-ctrlr/src/controllers/suite_test.go
platform/crd-ctrlr/src/main.go
platform/crd-ctrlr/src/openwrt/route.go [new file with mode: 0644]

index 48edbb1..b5ddfd6 100644 (file)
@@ -7,6 +7,79 @@ metadata:
 ---
 apiVersion: apiextensions.k8s.io/v1beta1
 kind: CustomResourceDefinition
+metadata:
+  annotations:
+    controller-gen.kubebuilder.io/version: v0.2.5
+  creationTimestamp: null
+  name: cnfroutes.batch.sdewan.akraino.org
+spec:
+  group: batch.sdewan.akraino.org
+  names:
+    kind: CNFRoute
+    listKind: CNFRouteList
+    plural: cnfroutes
+    singular: cnfroute
+  scope: Namespaced
+  subresources:
+    status: {}
+  validation:
+    openAPIV3Schema:
+      description: CNFRoute is the Schema for the cnfroutes 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: CNFRouteSpec defines the desired state of CNFRoute
+          properties:
+            dev:
+              type: string
+            dst:
+              type: string
+            gw:
+              type: string
+            table:
+              enum:
+              - default
+              - cnf
+              type: string
+          type: object
+        status:
+          description: status subsource used for Sdewan rule CRDs
+          properties:
+            appliedGeneration:
+              format: int64
+              type: integer
+            appliedTime:
+              format: date-time
+              type: string
+            message:
+              type: string
+            state:
+              type: string
+          required:
+          - state
+          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
@@ -1253,6 +1326,26 @@ rules:
   - get
   - list
   - watch
+- apiGroups:
+  - batch.sdewan.akraino.org
+  resources:
+  - cnfroutes
+  verbs:
+  - create
+  - delete
+  - get
+  - list
+  - patch
+  - update
+  - watch
+- apiGroups:
+  - batch.sdewan.akraino.org
+  resources:
+  - cnfroutes/status
+  verbs:
+  - get
+  - patch
+  - update
 - apiGroups:
   - batch.sdewan.akraino.org
   resources:
index 26c2994..eee5715 100644 (file)
@@ -40,4 +40,7 @@ resources:
 - group: batch
   kind: CNFStatus
   version: v1alpha1
+- group: batch
+  kind: CNFRoute
+  version: v1alpha1
 version: "2"
diff --git a/platform/crd-ctrlr/src/api/v1alpha1/cnfroute_types.go b/platform/crd-ctrlr/src/api/v1alpha1/cnfroute_types.go
new file mode 100644 (file)
index 0000000..8cceaa9
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+
+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.
+
+// CNFRouteSpec defines the desired state of CNFRoute
+type CNFRouteSpec struct {
+       Dst string `json:"dst,omitempty"`
+       Gw  string `json:"gw,omitempty"`
+       Dev string `json:"dev,omitempty"`
+       // +kubebuilder:validation:Enum=default;cnf
+       Table string `json:"table,omitempty"`
+}
+
+// +kubebuilder:object:root=true
+// +kubebuilder:subresource:status
+
+// CNFRoute is the Schema for the cnfroutes API
+type CNFRoute struct {
+       metav1.TypeMeta   `json:",inline"`
+       metav1.ObjectMeta `json:"metadata,omitempty"`
+
+       Spec   CNFRouteSpec `json:"spec,omitempty"`
+       Status SdewanStatus `json:"status,omitempty"`
+}
+
+// +kubebuilder:object:root=true
+
+// CNFRouteList contains a list of CNFRoute
+type CNFRouteList struct {
+       metav1.TypeMeta `json:",inline"`
+       metav1.ListMeta `json:"metadata,omitempty"`
+       Items           []CNFRoute `json:"items"`
+}
+
+func init() {
+       SchemeBuilder.Register(&CNFRoute{}, &CNFRouteList{})
+}
index 9a21a7a..cf75319 100644 (file)
@@ -68,6 +68,80 @@ func (in BucketPermission) DeepCopy() BucketPermission {
        return *out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *CNFRoute) DeepCopyInto(out *CNFRoute) {
+       *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 CNFRoute.
+func (in *CNFRoute) DeepCopy() *CNFRoute {
+       if in == nil {
+               return nil
+       }
+       out := new(CNFRoute)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *CNFRoute) 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 *CNFRouteList) DeepCopyInto(out *CNFRouteList) {
+       *out = *in
+       out.TypeMeta = in.TypeMeta
+       in.ListMeta.DeepCopyInto(&out.ListMeta)
+       if in.Items != nil {
+               in, out := &in.Items, &out.Items
+               *out = make([]CNFRoute, len(*in))
+               for i := range *in {
+                       (*in)[i].DeepCopyInto(&(*out)[i])
+               }
+       }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CNFRouteList.
+func (in *CNFRouteList) DeepCopy() *CNFRouteList {
+       if in == nil {
+               return nil
+       }
+       out := new(CNFRouteList)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *CNFRouteList) 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 *CNFRouteSpec) DeepCopyInto(out *CNFRouteSpec) {
+       *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CNFRouteSpec.
+func (in *CNFRouteSpec) DeepCopy() *CNFRouteSpec {
+       if in == nil {
+               return nil
+       }
+       out := new(CNFRouteSpec)
+       in.DeepCopyInto(out)
+       return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *CNFService) DeepCopyInto(out *CNFService) {
        *out = *in
diff --git a/platform/crd-ctrlr/src/config/crd/bases/batch.sdewan.akraino.org_cnfroutes.yaml b/platform/crd-ctrlr/src/config/crd/bases/batch.sdewan.akraino.org_cnfroutes.yaml
new file mode 100644 (file)
index 0000000..d8dd4f4
--- /dev/null
@@ -0,0 +1,78 @@
+
+---
+apiVersion: apiextensions.k8s.io/v1beta1
+kind: CustomResourceDefinition
+metadata:
+  annotations:
+    controller-gen.kubebuilder.io/version: v0.2.5
+  creationTimestamp: null
+  name: cnfroutes.batch.sdewan.akraino.org
+spec:
+  group: batch.sdewan.akraino.org
+  names:
+    kind: CNFRoute
+    listKind: CNFRouteList
+    plural: cnfroutes
+    singular: cnfroute
+  scope: Namespaced
+  subresources:
+    status: {}
+  validation:
+    openAPIV3Schema:
+      description: CNFRoute is the Schema for the cnfroutes 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: CNFRouteSpec defines the desired state of CNFRoute
+          properties:
+            dev:
+              type: string
+            dst:
+              type: string
+            gw:
+              type: string
+            table:
+              enum:
+              - default
+              - cnf
+              type: string
+          type: object
+        status:
+          description: status subsource used for Sdewan rule CRDs
+          properties:
+            appliedGeneration:
+              format: int64
+              type: integer
+            appliedTime:
+              format: date-time
+              type: string
+            message:
+              type: string
+            state:
+              type: string
+          required:
+          - state
+          type: object
+      type: object
+  version: v1alpha1
+  versions:
+  - name: v1alpha1
+    served: true
+    storage: true
+status:
+  acceptedNames:
+    kind: ""
+    plural: ""
+  conditions: []
+  storedVersions: []
index 54a6b47..d43e045 100644 (file)
@@ -15,6 +15,7 @@ resources:
 - bases/batch.sdewan.akraino.org_cnfservices.yaml
 - bases/batch.sdewan.akraino.org_sdewanapplications.yaml
 - bases/batch.sdewan.akraino.org_cnfstatuses.yaml
+- bases/batch.sdewan.akraino.org_cnfroutes.yaml
 # +kubebuilder:scaffold:crdkustomizeresource
 
 patchesStrategicMerge:
@@ -33,6 +34,7 @@ patchesStrategicMerge:
 #- patches/webhook_in_cnfservices.yaml
 #- patches/webhook_in_sdewanapplications.yaml
 #- patches/webhook_in_cnfstatuses.yaml
+#- patches/webhook_in_cnfroutes.yaml
 # +kubebuilder:scaffold:crdkustomizewebhookpatch
 
 # [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix.
@@ -50,6 +52,7 @@ patchesStrategicMerge:
 #- patches/cainjection_in_cnfservices.yaml
 #- patches/cainjection_in_sdewanapplications.yaml
 #- patches/cainjection_in_cnfstatuses.yaml
+#- patches/cainjection_in_cnfroutes.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_cnfroutes.yaml b/platform/crd-ctrlr/src/config/crd/patches/cainjection_in_cnfroutes.yaml
new file mode 100644 (file)
index 0000000..84c0120
--- /dev/null
@@ -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: cnfroutes.batch.sdewan.akraino.org
diff --git a/platform/crd-ctrlr/src/config/crd/patches/webhook_in_cnfroutes.yaml b/platform/crd-ctrlr/src/config/crd/patches/webhook_in_cnfroutes.yaml
new file mode 100644 (file)
index 0000000..504e81c
--- /dev/null
@@ -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: cnfroutes.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/cnfroute_editor_role.yaml b/platform/crd-ctrlr/src/config/rbac/cnfroute_editor_role.yaml
new file mode 100644 (file)
index 0000000..4ad5146
--- /dev/null
@@ -0,0 +1,24 @@
+# permissions for end users to edit cnfroutes.
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: cnfroute-editor-role
+rules:
+- apiGroups:
+  - batch.sdewan.akraino.org
+  resources:
+  - cnfroutes
+  verbs:
+  - create
+  - delete
+  - get
+  - list
+  - patch
+  - update
+  - watch
+- apiGroups:
+  - batch.sdewan.akraino.org
+  resources:
+  - cnfroutes/status
+  verbs:
+  - get
diff --git a/platform/crd-ctrlr/src/config/rbac/cnfroute_viewer_role.yaml b/platform/crd-ctrlr/src/config/rbac/cnfroute_viewer_role.yaml
new file mode 100644 (file)
index 0000000..af5e474
--- /dev/null
@@ -0,0 +1,20 @@
+# permissions for end users to view cnfroutes.
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: cnfroute-viewer-role
+rules:
+- apiGroups:
+  - batch.sdewan.akraino.org
+  resources:
+  - cnfroutes
+  verbs:
+  - get
+  - list
+  - watch
+- apiGroups:
+  - batch.sdewan.akraino.org
+  resources:
+  - cnfroutes/status
+  verbs:
+  - get
index c2ce53f..24215d5 100644 (file)
@@ -22,6 +22,26 @@ rules:
   - get
   - list
   - watch
+- apiGroups:
+  - batch.sdewan.akraino.org
+  resources:
+  - cnfroutes
+  verbs:
+  - create
+  - delete
+  - get
+  - list
+  - patch
+  - update
+  - watch
+- apiGroups:
+  - batch.sdewan.akraino.org
+  resources:
+  - cnfroutes/status
+  verbs:
+  - get
+  - patch
+  - update
 - apiGroups:
   - batch.sdewan.akraino.org
   resources:
diff --git a/platform/crd-ctrlr/src/config/samples/batch_v1alpha1_cnfroute.yaml b/platform/crd-ctrlr/src/config/samples/batch_v1alpha1_cnfroute.yaml
new file mode 100644 (file)
index 0000000..ef0f161
--- /dev/null
@@ -0,0 +1,11 @@
+apiVersion: batch.sdewan.akraino.org/v1alpha1
+kind: CNFRoute
+metadata:
+  name: cnfroute-sample
+  labels:
+    sdewanPurpose: cnf1
+spec:
+    dst: "192.167.23.0/24"
+    gw: "172.16.44.11"
+    dev: "net1"
+    table: "cnf"
diff --git a/platform/crd-ctrlr/src/controllers/cnfroute_controller.go b/platform/crd-ctrlr/src/controllers/cnfroute_controller.go
new file mode 100644 (file)
index 0000000..f8ebdc3
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+
+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"
+       "reflect"
+
+       "github.com/go-logr/logr"
+       appsv1 "k8s.io/api/apps/v1"
+       "k8s.io/apimachinery/pkg/runtime"
+       ctrl "sigs.k8s.io/controller-runtime"
+       "sigs.k8s.io/controller-runtime/pkg/client"
+       "sigs.k8s.io/controller-runtime/pkg/handler"
+       "sigs.k8s.io/controller-runtime/pkg/source"
+
+       batchv1alpha1 "sdewan.akraino.org/sdewan/api/v1alpha1"
+       "sdewan.akraino.org/sdewan/openwrt"
+)
+
+var cnfRouteHandler = new(CNFRouteHandler)
+
+type CNFRouteHandler struct {
+}
+
+func (m *CNFRouteHandler) GetType() string {
+       return "cnfRoute"
+}
+
+func (m *CNFRouteHandler) GetName(instance runtime.Object) string {
+       route := instance.(*batchv1alpha1.CNFRoute)
+       return route.Name
+}
+
+func (m *CNFRouteHandler) GetFinalizer() string {
+       return "rule.finalizers.sdewan.akraino.org"
+}
+
+func (m *CNFRouteHandler) GetInstance(r client.Client, ctx context.Context, req ctrl.Request) (runtime.Object, error) {
+       instance := &batchv1alpha1.CNFRoute{}
+       err := r.Get(ctx, req.NamespacedName, instance)
+       return instance, err
+}
+
+func (m *CNFRouteHandler) Convert(instance runtime.Object, deployment appsv1.Deployment) (openwrt.IOpenWrtObject, error) {
+       route := instance.(*batchv1alpha1.CNFRoute)
+       openwrtroute := openwrt.SdewanRoute{
+               Name:  route.Name,
+               Dst:   route.Spec.Dst,
+               Gw:    route.Spec.Gw,
+               Dev:   route.Spec.Dev,
+               Table: route.Spec.Table,
+       }
+       return &openwrtroute, nil
+}
+
+func (m *CNFRouteHandler) IsEqual(instance1 openwrt.IOpenWrtObject, instance2 openwrt.IOpenWrtObject) bool {
+       route1 := instance1.(*openwrt.SdewanRoute)
+       route2 := instance2.(*openwrt.SdewanRoute)
+       return reflect.DeepEqual(*route1, *route2)
+}
+
+func (m *CNFRouteHandler) GetObject(clientInfo *openwrt.OpenwrtClientInfo, name string) (openwrt.IOpenWrtObject, error) {
+       openwrtClient := openwrt.GetOpenwrtClient(*clientInfo)
+       route := openwrt.RouteClient{OpenwrtClient: openwrtClient}
+       ret, err := route.GetRoute(name)
+       return ret, err
+}
+
+func (m *CNFRouteHandler) CreateObject(clientInfo *openwrt.OpenwrtClientInfo, instance openwrt.IOpenWrtObject) (openwrt.IOpenWrtObject, error) {
+       openwrtClient := openwrt.GetOpenwrtClient(*clientInfo)
+       route := openwrt.RouteClient{OpenwrtClient: openwrtClient}
+       obj := instance.(*openwrt.SdewanRoute)
+       return route.CreateRoute(*obj)
+}
+
+func (m *CNFRouteHandler) UpdateObject(clientInfo *openwrt.OpenwrtClientInfo, instance openwrt.IOpenWrtObject) (openwrt.IOpenWrtObject, error) {
+       openwrtClient := openwrt.GetOpenwrtClient(*clientInfo)
+       route := openwrt.RouteClient{OpenwrtClient: openwrtClient}
+       obj := instance.(*openwrt.SdewanRoute)
+       return route.UpdateRoute(*obj)
+}
+
+func (m *CNFRouteHandler) DeleteObject(clientInfo *openwrt.OpenwrtClientInfo, name string) error {
+       openwrtClient := openwrt.GetOpenwrtClient(*clientInfo)
+       route := openwrt.RouteClient{OpenwrtClient: openwrtClient}
+       return route.DeleteRoute(name)
+}
+
+func (m *CNFRouteHandler) Restart(clientInfo *openwrt.OpenwrtClientInfo) (bool, error) {
+       return true, nil
+}
+
+// CNFRouteReconciler reconciles a CNFRoute object
+type CNFRouteReconciler struct {
+       client.Client
+       Log    logr.Logger
+       Scheme *runtime.Scheme
+}
+
+// +kubebuilder:rbac:groups=batch.sdewan.akraino.org,resources=cnfroutes,verbs=get;list;watch;create;update;patch;delete
+// +kubebuilder:rbac:groups=batch.sdewan.akraino.org,resources=cnfroutes/status,verbs=get;update;patch
+
+func (r *CNFRouteReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
+       return ProcessReconcile(r, r.Log, req, cnfRouteHandler)
+}
+
+func (r *CNFRouteReconciler) SetupWithManager(mgr ctrl.Manager) error {
+       return ctrl.NewControllerManagedBy(mgr).
+               For(&batchv1alpha1.CNFRoute{}).
+               Watches(
+                       &source.Kind{Type: &appsv1.Deployment{}},
+                       &handler.EnqueueRequestsFromMapFunc{
+                               ToRequests: handler.ToRequestsFunc(GetToRequestsFunc(r, &batchv1alpha1.CNFRouteList{})),
+                       },
+                       Filter).
+               Complete(r)
+}
index bf86e57..f48b8b4 100644 (file)
@@ -95,6 +95,9 @@ var _ = BeforeSuite(func(done Done) {
        err = batchv1alpha1.AddToScheme(scheme.Scheme)
        Expect(err).NotTo(HaveOccurred())
 
+       err = batchv1alpha1.AddToScheme(scheme.Scheme)
+       Expect(err).NotTo(HaveOccurred())
+
        // +kubebuilder:scaffold:scheme
 
        k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
index beb3dee..a516398 100644 (file)
@@ -229,6 +229,14 @@ func main() {
                setupLog.Error(err, "unable to create controller", "controller", "SdewanApplication")
                os.Exit(1)
        }
+       if err = (&controllers.CNFRouteReconciler{
+               Client: mgr.GetClient(),
+               Log:    ctrl.Log.WithName("controllers").WithName("CNFRoute"),
+               Scheme: mgr.GetScheme(),
+       }).SetupWithManager(mgr); err != nil {
+               setupLog.Error(err, "unable to create controller", "controller", "CNFRoute")
+               os.Exit(1)
+       }
        // +kubebuilder:scaffold:builder
 
        setupLog.Info("start CNFStatusController to query CNF status periodicly")
diff --git a/platform/crd-ctrlr/src/openwrt/route.go b/platform/crd-ctrlr/src/openwrt/route.go
new file mode 100644 (file)
index 0000000..797ef54
--- /dev/null
@@ -0,0 +1,108 @@
+package openwrt
+
+import (
+       "encoding/json"
+)
+
+const (
+       routeBaseURL = "sdewan/route/v1/"
+)
+
+type RouteClient struct {
+       OpenwrtClient *openwrtClient
+}
+
+// Route Info
+type SdewanRoute struct {
+       Name  string `json:"name"`
+       Dst   string `json:"dst"`
+       Gw    string `json:"gw"`
+       Dev   string `json:"dev"`
+       Table string `json:"table"`
+}
+
+type SdewanRoutes struct {
+       Routes []SdewanRoute `json:"routes"`
+}
+
+func (o *SdewanRoute) GetName() string {
+       return o.Name
+}
+
+// Route APIs
+// get routes
+func (m *RouteClient) GetRoutes() (*SdewanRoutes, error) {
+       response, err := m.OpenwrtClient.Get(routeBaseURL + "routes")
+       if err != nil {
+               return nil, err
+       }
+
+       var sdewanRoutes SdewanRoutes
+       err2 := json.Unmarshal([]byte(response), &sdewanRoutes)
+       if err2 != nil {
+               return nil, err2
+       }
+
+       return &sdewanRoutes, nil
+}
+
+// get route
+func (m *RouteClient) GetRoute(route_name string) (*SdewanRoute, error) {
+       response, err := m.OpenwrtClient.Get(routeBaseURL + "routes/" + route_name)
+       if err != nil {
+               return nil, err
+       }
+
+       var sdewanRoute SdewanRoute
+       err2 := json.Unmarshal([]byte(response), &sdewanRoute)
+       if err2 != nil {
+               return nil, err2
+       }
+
+       return &sdewanRoute, nil
+}
+
+// create route
+func (m *RouteClient) CreateRoute(route SdewanRoute) (*SdewanRoute, error) {
+       route_obj, _ := json.Marshal(route)
+       response, err := m.OpenwrtClient.Post(routeBaseURL+"routes/", string(route_obj))
+       if err != nil {
+               return nil, err
+       }
+
+       var sdewanRoute SdewanRoute
+       err2 := json.Unmarshal([]byte(response), &sdewanRoute)
+       if err2 != nil {
+               return nil, err2
+       }
+
+       return &sdewanRoute, nil
+}
+
+// delete route
+func (m *RouteClient) DeleteRoute(route_name string) error {
+       _, err := m.OpenwrtClient.Delete(routeBaseURL + "routes/" + route_name)
+       if err != nil {
+               return err
+       }
+
+       return nil
+}
+
+// update route
+func (m *RouteClient) UpdateRoute(route SdewanRoute) (*SdewanRoute, error) {
+       route_obj, _ := json.Marshal(route)
+       route_name := route.Name
+       response, err := m.OpenwrtClient.Put(routeBaseURL+"routes/"+route_name, string(route_obj))
+       if err != nil {
+               return nil, err
+       }
+
+       var sdewanRoute SdewanRoute
+       err2 := json.Unmarshal([]byte(response), &sdewanRoute)
+       if err2 != nil {
+               return nil, err2
+       }
+
+       return &sdewanRoute, nil
+}