Service CR implemention 89/3789/3
authorYao Le <le.yao@intel.com>
Sun, 27 Sep 2020 08:29:44 +0000 (08:29 +0000)
committerYao Le <le.yao@intel.com>
Mon, 12 Oct 2020 06:01:42 +0000 (06:01 +0000)
When apply a Service CR, the controller will call service RESTful API
to configure iptables in CNF.

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

platform/crd-ctrlr/src/api/v1alpha1/cnfservice_types.go
platform/crd-ctrlr/src/api/v1alpha1/zz_generated.deepcopy.go
platform/crd-ctrlr/src/config/crd/bases/batch.sdewan.akraino.org_cnfservices.yaml
platform/crd-ctrlr/src/config/samples/batch_v1alpha1_cnfservice.yaml
platform/crd-ctrlr/src/controllers/cnfservice_controller.go
platform/crd-ctrlr/src/openwrt/svc.go [new file with mode: 0644]

index ad73fbf..10660c1 100644 (file)
@@ -24,24 +24,21 @@ import (
 
 // CNFServiceSpec defines the desired state of CNFService
 type CNFServiceSpec struct {
-       Name string `json:"name,omitempty"`
-}
-
-// CNFServiceStatus defines the observed state of CNFService
-type CNFServiceStatus struct {
-       // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
-       // Important: Run "make" to regenerate code after modifying this file
+       FullName string `json:"fullname,omitempty"`
+       Port     string `json:"port,omitempty"`
+       DPort    string `json:"dport,omitempty"`
 }
 
 // +kubebuilder:object:root=true
+// +kubebuilder:subresource:status
 
 // CNFService is the Schema for the cnfservices API
 type CNFService struct {
        metav1.TypeMeta   `json:",inline"`
        metav1.ObjectMeta `json:"metadata,omitempty"`
 
-       Spec   CNFServiceSpec   `json:"spec,omitempty"`
-       Status CNFServiceStatus `json:"status,omitempty"`
+       Spec   CNFServiceSpec `json:"spec,omitempty"`
+       Status SdewanStatus   `json:"status,omitempty"`
 }
 
 // +kubebuilder:object:root=true
index 3216eea..83a43ee 100644 (file)
@@ -58,7 +58,7 @@ func (in *CNFService) DeepCopyInto(out *CNFService) {
        out.TypeMeta = in.TypeMeta
        in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
        out.Spec = in.Spec
-       out.Status = in.Status
+       in.Status.DeepCopyInto(&out.Status)
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CNFService.
@@ -126,21 +126,6 @@ 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 *CNFServiceStatus) DeepCopyInto(out *CNFServiceStatus) {
-       *out = *in
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CNFServiceStatus.
-func (in *CNFServiceStatus) DeepCopy() *CNFServiceStatus {
-       if in == nil {
-               return nil
-       }
-       out := new(CNFServiceStatus)
-       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
index 09ad424..948dceb 100644 (file)
@@ -15,6 +15,8 @@ spec:
     plural: cnfservices
     singular: cnfservice
   scope: Namespaced
+  subresources:
+    status: {}
   validation:
     openAPIV3Schema:
       description: CNFService is the Schema for the cnfservices API
@@ -34,11 +36,28 @@ spec:
         spec:
           description: CNFServiceSpec defines the desired state of CNFService
           properties:
-            name:
+            dport:
+              type: string
+            fullname:
+              type: string
+            port:
               type: string
           type: object
         status:
-          description: CNFServiceStatus defines the observed state of CNFService
+          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
index a3f2ddb..d4664f2 100644 (file)
@@ -2,6 +2,9 @@ apiVersion: batch.sdewan.akraino.org/v1alpha1
 kind: CNFService
 metadata:
   name: cnfservice-sample
+  labels:
+    sdewanPurpose: cnf1
 spec:
-  # Add fields here
-  foo: bar
+    fullname: foo.default.svc.cluster.local
+    port: "8866"
+    dport: "8080"
index 2dc0d8d..7047347 100644 (file)
@@ -17,6 +17,7 @@ package controllers
 
 import (
        "context"
+       "reflect"
 
        "github.com/go-logr/logr"
        appsv1 "k8s.io/api/apps/v1"
@@ -56,33 +57,51 @@ func (m *CNFServiceHandler) GetInstance(r client.Client, ctx context.Context, re
 }
 
 func (m *CNFServiceHandler) Convert(instance runtime.Object, deployment appsv1.Deployment) (openwrt.IOpenWrtObject, error) {
-       return nil, nil
+       svc := instance.(*batchv1alpha1.CNFService)
+       openwrtsvc := openwrt.SdewanSvc{
+               Name:     svc.Name,
+               FullName: svc.Spec.FullName,
+               Port:     svc.Spec.Port,
+               DPort:    svc.Spec.DPort,
+       }
+       return &openwrtsvc, nil
 }
 
 func (m *CNFServiceHandler) IsEqual(instance1 openwrt.IOpenWrtObject, instance2 openwrt.IOpenWrtObject) bool {
-       return false
+       service1 := instance1.(*openwrt.SdewanSvc)
+       service2 := instance2.(*openwrt.SdewanSvc)
+       return reflect.DeepEqual(*service1, *service2)
 }
 
 func (m *CNFServiceHandler) GetObject(clientInfo *openwrt.OpenwrtClientInfo, name string) (openwrt.IOpenWrtObject, error) {
-       return nil, nil
+       openwrtClient := openwrt.GetOpenwrtClient(*clientInfo)
+       svc := openwrt.SvcClient{OpenwrtClient: openwrtClient}
+       ret, err := svc.GetSvc(name)
+       return ret, err
 }
 
 func (m *CNFServiceHandler) CreateObject(clientInfo *openwrt.OpenwrtClientInfo, instance openwrt.IOpenWrtObject) (openwrt.IOpenWrtObject, error) {
-       return nil, nil
+       openwrtClient := openwrt.GetOpenwrtClient(*clientInfo)
+       svc := openwrt.SvcClient{OpenwrtClient: openwrtClient}
+       service := instance.(*openwrt.SdewanSvc)
+       return svc.CreateSvc(*service)
 }
 
 func (m *CNFServiceHandler) UpdateObject(clientInfo *openwrt.OpenwrtClientInfo, instance openwrt.IOpenWrtObject) (openwrt.IOpenWrtObject, error) {
-       return nil, nil
+       openwrtClient := openwrt.GetOpenwrtClient(*clientInfo)
+       svc := openwrt.SvcClient{OpenwrtClient: openwrtClient}
+       service := instance.(*openwrt.SdewanSvc)
+       return svc.UpdateSvc(*service)
 }
 
 func (m *CNFServiceHandler) DeleteObject(clientInfo *openwrt.OpenwrtClientInfo, name string) error {
-       return nil
+       openwrtClient := openwrt.GetOpenwrtClient(*clientInfo)
+       svc := openwrt.SvcClient{OpenwrtClient: openwrtClient}
+       return svc.DeleteSvc(name)
 }
 
 func (m *CNFServiceHandler) Restart(clientInfo *openwrt.OpenwrtClientInfo) (bool, error) {
-       openwrtClient := openwrt.GetOpenwrtClient(*clientInfo)
-       service := openwrt.ServiceClient{OpenwrtClient: openwrtClient}
-       return service.ExecuteService("cnfService", "restart")
+       return true, nil
 }
 
 // CNFServiceReconciler reconciles a CNFService object
diff --git a/platform/crd-ctrlr/src/openwrt/svc.go b/platform/crd-ctrlr/src/openwrt/svc.go
new file mode 100644 (file)
index 0000000..2210e87
--- /dev/null
@@ -0,0 +1,107 @@
+package openwrt
+
+import (
+       "encoding/json"
+)
+
+const (
+       svcBaseURL = "sdewan/service/v1/"
+)
+
+type SvcClient struct {
+       OpenwrtClient *openwrtClient
+}
+
+// Svc Info
+type SdewanSvc struct {
+       Name     string `json:"name"`
+       FullName string `json:"fullname"`
+       Port     string `json:"port"`
+       DPort    string `json:"dport"`
+}
+
+type SdewanSvcs struct {
+       Svcs []SdewanSvc `json:"svcs"`
+}
+
+func (o *SdewanSvc) GetName() string {
+       return o.Name
+}
+
+// Svc APIs
+// get svcs
+func (m *SvcClient) GetSvcs() (*SdewanSvcs, error) {
+       response, err := m.OpenwrtClient.Get(svcBaseURL + "services")
+       if err != nil {
+               return nil, err
+       }
+
+       var sdewanSvcs SdewanSvcs
+       err2 := json.Unmarshal([]byte(response), &sdewanSvcs)
+       if err2 != nil {
+               return nil, err2
+       }
+
+       return &sdewanSvcs, nil
+}
+
+// get svc
+func (m *SvcClient) GetSvc(svc_name string) (*SdewanSvc, error) {
+       response, err := m.OpenwrtClient.Get(svcBaseURL + "services/" + svc_name)
+       if err != nil {
+               return nil, err
+       }
+
+       var sdewanSvc SdewanSvc
+       err2 := json.Unmarshal([]byte(response), &sdewanSvc)
+       if err2 != nil {
+               return nil, err2
+       }
+
+       return &sdewanSvc, nil
+}
+
+// create svc
+func (m *SvcClient) CreateSvc(svc SdewanSvc) (*SdewanSvc, error) {
+       svc_obj, _ := json.Marshal(svc)
+       response, err := m.OpenwrtClient.Post(svcBaseURL+"services/", string(svc_obj))
+       if err != nil {
+               return nil, err
+       }
+
+       var sdewanSvc SdewanSvc
+       err2 := json.Unmarshal([]byte(response), &sdewanSvc)
+       if err2 != nil {
+               return nil, err2
+       }
+
+       return &sdewanSvc, nil
+}
+
+// delete svc
+func (m *SvcClient) DeleteSvc(svc_name string) error {
+       _, err := m.OpenwrtClient.Delete(svcBaseURL + "services/" + svc_name)
+       if err != nil {
+               return err
+       }
+
+       return nil
+}
+
+// update svc
+func (m *SvcClient) UpdateSvc(svc SdewanSvc) (*SdewanSvc, error) {
+       svc_obj, _ := json.Marshal(svc)
+       svc_name := svc.Name
+       response, err := m.OpenwrtClient.Put(svcBaseURL+"services/"+svc_name, string(svc_obj))
+       if err != nil {
+               return nil, err
+       }
+
+       var sdewanSvc SdewanSvc
+       err2 := json.Unmarshal([]byte(response), &sdewanSvc)
+       if err2 != nil {
+               return nil, err2
+       }
+
+       return &sdewanSvc, nil
+}