Add CRD for IpsecSite 75/3575/8
authorroot <root@edge-b>
Tue, 16 Jun 2020 09:09:49 +0000 (09:09 +0000)
committerRuoyu <ruoyu.ying@intel.com>
Wed, 17 Jun 2020 01:52:40 +0000 (09:52 +0800)
 * Add changes for another IPSec crd: IpsecSite

Issue-ID: ICN-289
Change-Id: I9c76c28ec22640b0089e0bc097a316af68b6fd19
Signed-off-by: Ruoyu <ruoyu.ying@intel.com>
18 files changed:
platform/crd-ctrlr/README.md
platform/crd-ctrlr/examples/sdewan-controller.yaml
platform/crd-ctrlr/src/PROJECT
platform/crd-ctrlr/src/api/v1alpha1/bucket_permission_webhook.go
platform/crd-ctrlr/src/api/v1alpha1/ipsecsite_types.go [new file with mode: 0644]
platform/crd-ctrlr/src/api/v1alpha1/label_validate_webhook.go
platform/crd-ctrlr/src/api/v1alpha1/zz_generated.deepcopy.go
platform/crd-ctrlr/src/config/crd/bases/batch.sdewan.akraino.org_ipsecsites.yaml [new file with mode: 0644]
platform/crd-ctrlr/src/config/crd/kustomization.yaml
platform/crd-ctrlr/src/config/crd/patches/cainjection_in_ipsecsites.yaml [new file with mode: 0644]
platform/crd-ctrlr/src/config/crd/patches/webhook_in_ipsecsites.yaml [new file with mode: 0644]
platform/crd-ctrlr/src/config/local/webhook_config.yaml
platform/crd-ctrlr/src/config/rbac/role.yaml
platform/crd-ctrlr/src/config/samples/batch_v1alpha1_ipsecsite.yaml [new file with mode: 0644]
platform/crd-ctrlr/src/config/webhook/manifests.yaml
platform/crd-ctrlr/src/controllers/ipsecsite_controller.go [new file with mode: 0644]
platform/crd-ctrlr/src/controllers/suite_test.go
platform/crd-ctrlr/src/main.go

index 78267eb..9507b78 100644 (file)
@@ -116,11 +116,11 @@ make gen-yaml IMG="integratedcloudnative/sdewan-controller:dev"
   - FirewallSNAT
   - IpsecProposal
   - IpsecHost
+  - IpsecSite
 
 ### What we don't have yet
 
 - Add a watch for deployment, so that the controller can get the CNF ready status change. [predicate feature](https://godoc.org/sigs.k8s.io/controller-runtime/pkg/predicate#example-Funcs) should be used to filter no-status event.
-- Implemente the ipsec CRDs/controllers 
 - Add validation webhook to validate CR ( as we have the validation in openwrt, so not validate the CR at frontend)
 
 ### NOTEs
index 98cc9a5..2161930 100644 (file)
@@ -694,6 +694,141 @@ status:
 ---
 apiVersion: apiextensions.k8s.io/v1beta1
 kind: CustomResourceDefinition
+metadata:
+  annotations:
+    controller-gen.kubebuilder.io/version: v0.2.5
+  creationTimestamp: null
+  name: ipsecsites.batch.sdewan.akraino.org
+spec:
+  group: batch.sdewan.akraino.org
+  names:
+    kind: IpsecSite
+    listKind: IpsecSiteList
+    plural: ipsecsites
+    singular: ipsecsite
+  scope: Namespaced
+  subresources:
+    status: {}
+  validation:
+    openAPIV3Schema:
+      description: IpsecSite is the Schema for the ipsecsites 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: IpsecSiteSpec defines the desired state of IpsecSite
+          properties:
+            authentication_method:
+              type: string
+            connections:
+              items:
+                properties:
+                  conn_type:
+                    type: string
+                  crypto_proposal:
+                    items:
+                      type: string
+                    type: array
+                  if_id:
+                    type: string
+                  local_firewall:
+                    type: string
+                  local_subnet:
+                    type: string
+                  local_updown:
+                    type: string
+                  mark:
+                    type: string
+                  mode:
+                    type: string
+                  name:
+                    type: string
+                  remote_firewall:
+                    type: string
+                  remote_sourceip:
+                    type: string
+                  remote_subnet:
+                    type: string
+                  remote_updown:
+                    type: string
+                required:
+                - conn_type
+                - local_subnet
+                - mode
+                - name
+                type: object
+              type: array
+            crypto_proposal:
+              items:
+                type: string
+              type: array
+            force_crypto_proposal:
+              type: string
+            local_identifier:
+              type: string
+            local_private_cert:
+              type: string
+            local_public_cert:
+              type: string
+            name:
+              type: string
+            pre_shared_key:
+              type: string
+            remote:
+              type: string
+            remote_identifier:
+              type: string
+            shared_ca:
+              type: string
+            type:
+              type: string
+          required:
+          - authentication_method
+          - connections
+          - crypto_proposal
+          - remote
+          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
@@ -1068,6 +1203,26 @@ rules:
   - get
   - patch
   - update
+- apiGroups:
+  - batch.sdewan.akraino.org
+  resources:
+  - ipsecsites
+  verbs:
+  - create
+  - delete
+  - get
+  - list
+  - patch
+  - update
+  - watch
+- apiGroups:
+  - batch.sdewan.akraino.org
+  resources:
+  - ipsecsites/status
+  verbs:
+  - get
+  - patch
+  - update
 - apiGroups:
   - batch.sdewan.akraino.org
   resources:
@@ -1319,6 +1474,7 @@ webhooks:
     - firewalldnats
     - ipsecproposals
     - ipsechosts
+    - ipsecsites
 - clientConfig:
     caBundle: Cg==
     service:
@@ -1347,3 +1503,4 @@ webhooks:
     - firewalldnats
     - ipsecproposals
     - ipsechosts
+    - ipsecsites
index e282bff..53eb57c 100644 (file)
@@ -28,4 +28,7 @@ resources:
 - group: batch
   kind: IpsecHost
   version: v1alpha1
+- group: batch
+  kind: IpsecSite
+  version: v1alpha1
 version: "2"
index adf9c11..0982260 100644 (file)
@@ -45,7 +45,7 @@ func SetupBucketPermissionWebhookWithManager(mgr ctrl.Manager) error {
        return nil
 }
 
-// +kubebuilder:webhook:path=/validate-sdewan-bucket-permission,mutating=false,failurePolicy=fail,groups="batch.sdewan.akraino.org",resources=mwan3policies;mwan3rules;firewallzones;firewallforwardings;firewallrules;firewallsnats;firewalldnats;ipsecproposals;ipsechosts,verbs=create;update;delete,versions=v1alpha1,name=validate-sdewan-bucket.akraino.org
+// +kubebuilder:webhook:path=/validate-sdewan-bucket-permission,mutating=false,failurePolicy=fail,groups="batch.sdewan.akraino.org",resources=mwan3policies;mwan3rules;firewallzones;firewallforwardings;firewallrules;firewallsnats;firewalldnats;ipsecproposals;ipsechosts;ipsecsites,verbs=create;update;delete,versions=v1alpha1,name=validate-sdewan-bucket.akraino.org
 
 // bucketPermissionValidator validates Pods
 type bucketPermissionValidator struct {
@@ -101,6 +101,8 @@ func (v *bucketPermissionValidator) Handle(ctx context.Context, req admission.Re
                obj = &IpsecProposal{}
        case "IpsecHost":
                obj = &IpsecHost{}
+       case "IpsecSite":
+               obj = &IpsecSite{}
        default:
                return admission.Errored(
                        http.StatusBadRequest,
diff --git a/platform/crd-ctrlr/src/api/v1alpha1/ipsecsite_types.go b/platform/crd-ctrlr/src/api/v1alpha1/ipsecsite_types.go
new file mode 100644 (file)
index 0000000..f0ef2fb
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+
+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"
+)
+
+type SiteConnection struct {
+       Name           string   `json:"name"`
+       ConnectionType string   `json:"conn_type"`
+       Mode           string   `json:"mode"`
+       LocalSubnet    string   `json:"local_subnet"`
+       LocalUpDown    string   `json:"local_updown,omitempty"`
+       LocalFirewall  string   `json:"local_firewall,omitempty"`
+       RemoteSubnet   string   `json:"remote_subnet,omitempty"`
+       RemoteSourceIp string   `json:"remote_sourceip,omitempty"`
+       RemoteUpDown   string   `json:"remote_updown,omitempty"`
+       RemoteFirewall string   `json:"remote_firewall,omitempty"`
+       CryptoProposal []string `json:"crypto_proposal,omitempty"`
+       Mark           string   `json:"mark,omitempty"`
+       IfId           string   `json:"if_id,omitempty"`
+}
+
+// IpsecSiteSpec defines the desired state of IpsecSite
+type IpsecSiteSpec struct {
+       Name                 string           `json:"name,omitempty"`
+       Type                 string           `json:"type,omitempty"`
+       Remote               string           `json:"remote"`
+       AuthenticationMethod string           `json:"authentication_method"`
+       CryptoProposal       []string         `json:"crypto_proposal"`
+       LocalIdentifier      string           `json:"local_identifier,omitempty"`
+       RemoteIdentifier     string           `json:"remote_identifier,omitempty"`
+       ForceCryptoProposal  string           `json:"force_crypto_proposal,omitempty"`
+       PresharedKey         string           `json:"pre_shared_key,omitempty"`
+       LocalPublicCert      string           `json:"local_public_cert,omitempty"`
+       LocalPrivateCert     string           `json:"local_private_cert,omitempty"`
+       SharedCA             string           `json:"shared_ca,omitempty"`
+       Connections          []SiteConnection `json:"connections"`
+}
+
+// +kubebuilder:object:root=true
+// +kubebuilder:subresource:status
+
+// IpsecSite is the Schema for the ipsecsites API
+type IpsecSite struct {
+       metav1.TypeMeta   `json:",inline"`
+       metav1.ObjectMeta `json:"metadata,omitempty"`
+
+       Spec   IpsecSiteSpec `json:"spec,omitempty"`
+       Status SdewanStatus  `json:"status,omitempty"`
+}
+
+// +kubebuilder:object:root=true
+
+// IpsecSiteList contains a list of IpsecSite
+type IpsecSiteList struct {
+       metav1.TypeMeta `json:",inline"`
+       metav1.ListMeta `json:"metadata,omitempty"`
+       Items           []IpsecSite `json:"items"`
+}
+
+func init() {
+       SchemeBuilder.Register(&IpsecSite{}, &IpsecSiteList{})
+}
index 5fe404e..9332c87 100644 (file)
@@ -42,7 +42,7 @@ func SetupLabelValidateWebhookWithManager(mgr ctrl.Manager) error {
        return nil
 }
 
-// +kubebuilder:webhook:path=/validate-label,mutating=false,failurePolicy=fail,groups=apps;batch.sdewan.akraino.org,resources=deployments;mwan3policies;mwan3rules;firewallzones;firewallforwardings;firewallrules;firewallsnats;firewalldnats;ipsecproposals;ipsechosts,verbs=update,versions=v1;v1alpha1,name=validate-label.akraino.org
+// +kubebuilder:webhook:path=/validate-label,mutating=false,failurePolicy=fail,groups=apps;batch.sdewan.akraino.org,resources=deployments;mwan3policies;mwan3rules;firewallzones;firewallforwardings;firewallrules;firewallsnats;firewalldnats;ipsecproposals;ipsechosts;ipsecsites,verbs=update,versions=v1;v1alpha1,name=validate-label.akraino.org
 
 type labelValidator struct {
        Client  client.Client
@@ -72,6 +72,8 @@ func (v *labelValidator) Handle(ctx context.Context, req admission.Request) admi
                obj = &IpsecProposal{}
        case "IpsecHost":
                obj = &IpsecHost{}
+       case "IpsecSite":
+               obj = &IpsecSite{}
        default:
                return admission.Errored(
                        http.StatusBadRequest,
index 29e7f04..07ce857 100644 (file)
@@ -627,6 +627,92 @@ func (in *IpsecProposalSpec) DeepCopy() *IpsecProposalSpec {
        return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *IpsecSite) DeepCopyInto(out *IpsecSite) {
+       *out = *in
+       out.TypeMeta = in.TypeMeta
+       in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+       in.Spec.DeepCopyInto(&out.Spec)
+       in.Status.DeepCopyInto(&out.Status)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IpsecSite.
+func (in *IpsecSite) DeepCopy() *IpsecSite {
+       if in == nil {
+               return nil
+       }
+       out := new(IpsecSite)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *IpsecSite) 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 *IpsecSiteList) DeepCopyInto(out *IpsecSiteList) {
+       *out = *in
+       out.TypeMeta = in.TypeMeta
+       in.ListMeta.DeepCopyInto(&out.ListMeta)
+       if in.Items != nil {
+               in, out := &in.Items, &out.Items
+               *out = make([]IpsecSite, len(*in))
+               for i := range *in {
+                       (*in)[i].DeepCopyInto(&(*out)[i])
+               }
+       }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IpsecSiteList.
+func (in *IpsecSiteList) DeepCopy() *IpsecSiteList {
+       if in == nil {
+               return nil
+       }
+       out := new(IpsecSiteList)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *IpsecSiteList) 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 *IpsecSiteSpec) DeepCopyInto(out *IpsecSiteSpec) {
+       *out = *in
+       if in.CryptoProposal != nil {
+               in, out := &in.CryptoProposal, &out.CryptoProposal
+               *out = make([]string, len(*in))
+               copy(*out, *in)
+       }
+       if in.Connections != nil {
+               in, out := &in.Connections, &out.Connections
+               *out = make([]SiteConnection, len(*in))
+               for i := range *in {
+                       (*in)[i].DeepCopyInto(&(*out)[i])
+               }
+       }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IpsecSiteSpec.
+func (in *IpsecSiteSpec) DeepCopy() *IpsecSiteSpec {
+       if in == nil {
+               return nil
+       }
+       out := new(IpsecSiteSpec)
+       in.DeepCopyInto(out)
+       return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Mwan3Policy) DeepCopyInto(out *Mwan3Policy) {
        *out = *in
@@ -813,3 +899,23 @@ func (in *SdewanStatus) DeepCopy() *SdewanStatus {
        in.DeepCopyInto(out)
        return out
 }
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SiteConnection) DeepCopyInto(out *SiteConnection) {
+       *out = *in
+       if in.CryptoProposal != nil {
+               in, out := &in.CryptoProposal, &out.CryptoProposal
+               *out = make([]string, len(*in))
+               copy(*out, *in)
+       }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SiteConnection.
+func (in *SiteConnection) DeepCopy() *SiteConnection {
+       if in == nil {
+               return nil
+       }
+       out := new(SiteConnection)
+       in.DeepCopyInto(out)
+       return out
+}
diff --git a/platform/crd-ctrlr/src/config/crd/bases/batch.sdewan.akraino.org_ipsecsites.yaml b/platform/crd-ctrlr/src/config/crd/bases/batch.sdewan.akraino.org_ipsecsites.yaml
new file mode 100644 (file)
index 0000000..c7bfced
--- /dev/null
@@ -0,0 +1,136 @@
+
+---
+apiVersion: apiextensions.k8s.io/v1beta1
+kind: CustomResourceDefinition
+metadata:
+  annotations:
+    controller-gen.kubebuilder.io/version: v0.2.5
+  creationTimestamp: null
+  name: ipsecsites.batch.sdewan.akraino.org
+spec:
+  group: batch.sdewan.akraino.org
+  names:
+    kind: IpsecSite
+    listKind: IpsecSiteList
+    plural: ipsecsites
+    singular: ipsecsite
+  scope: Namespaced
+  subresources:
+    status: {}
+  validation:
+    openAPIV3Schema:
+      description: IpsecSite is the Schema for the ipsecsites 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: IpsecSiteSpec defines the desired state of IpsecSite
+          properties:
+            authentication_method:
+              type: string
+            connections:
+              items:
+                properties:
+                  conn_type:
+                    type: string
+                  crypto_proposal:
+                    items:
+                      type: string
+                    type: array
+                  if_id:
+                    type: string
+                  local_firewall:
+                    type: string
+                  local_subnet:
+                    type: string
+                  local_updown:
+                    type: string
+                  mark:
+                    type: string
+                  mode:
+                    type: string
+                  name:
+                    type: string
+                  remote_firewall:
+                    type: string
+                  remote_sourceip:
+                    type: string
+                  remote_subnet:
+                    type: string
+                  remote_updown:
+                    type: string
+                required:
+                - conn_type
+                - local_subnet
+                - mode
+                - name
+                type: object
+              type: array
+            crypto_proposal:
+              items:
+                type: string
+              type: array
+            force_crypto_proposal:
+              type: string
+            local_identifier:
+              type: string
+            local_private_cert:
+              type: string
+            local_public_cert:
+              type: string
+            name:
+              type: string
+            pre_shared_key:
+              type: string
+            remote:
+              type: string
+            remote_identifier:
+              type: string
+            shared_ca:
+              type: string
+            type:
+              type: string
+          required:
+          - authentication_method
+          - connections
+          - crypto_proposal
+          - remote
+          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 1a470d7..915b9c8 100644 (file)
@@ -11,6 +11,7 @@ resources:
 - bases/batch.sdewan.akraino.org_firewallforwardings.yaml
 - bases/batch.sdewan.akraino.org_ipsecproposals.yaml
 - bases/batch.sdewan.akraino.org_ipsechosts.yaml
+- bases/batch.sdewan.akraino.org_ipsecsites.yaml
 # +kubebuilder:scaffold:crdkustomizeresource
 
 patchesStrategicMerge:
@@ -25,6 +26,7 @@ patchesStrategicMerge:
 #- patches/webhook_in_firewallforwardings.yaml
 #- patches/webhook_in_ipsecproposals.yaml
 #- patches/webhook_in_ipsechosts.yaml
+#- patches/webhook_in_ipsecsites.yaml
 # +kubebuilder:scaffold:crdkustomizewebhookpatch
 
 # [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix.
@@ -38,6 +40,7 @@ patchesStrategicMerge:
 #- patches/cainjection_in_firewallforwardings.yaml
 #- patches/cainjection_in_ipsecproposals.yaml
 #- patches/cainjection_in_ipsechosts.yaml
+#- patches/cainjection_in_ipsecsites.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_ipsecsites.yaml b/platform/crd-ctrlr/src/config/crd/patches/cainjection_in_ipsecsites.yaml
new file mode 100644 (file)
index 0000000..c7633b0
--- /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: ipsecsites.batch.sdewan.akraino.org
diff --git a/platform/crd-ctrlr/src/config/crd/patches/webhook_in_ipsecsites.yaml b/platform/crd-ctrlr/src/config/crd/patches/webhook_in_ipsecsites.yaml
new file mode 100644 (file)
index 0000000..8eab6c3
--- /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: ipsecsites.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
index d5025a5..d50877b 100644 (file)
@@ -30,6 +30,7 @@ webhooks:
     - firewallzones
     - ipsechosts
     - ipsecproposals
+    - ipsecsites
     scope: '*'
   sideEffects: Unknown
   timeoutSeconds: 30
index 8248c87..88ddf81 100644 (file)
@@ -162,6 +162,26 @@ rules:
   - get
   - patch
   - update
+- apiGroups:
+  - batch.sdewan.akraino.org
+  resources:
+  - ipsecsites
+  verbs:
+  - create
+  - delete
+  - get
+  - list
+  - patch
+  - update
+  - watch
+- apiGroups:
+  - batch.sdewan.akraino.org
+  resources:
+  - ipsecsites/status
+  verbs:
+  - get
+  - patch
+  - update
 - apiGroups:
   - batch.sdewan.akraino.org
   resources:
diff --git a/platform/crd-ctrlr/src/config/samples/batch_v1alpha1_ipsecsite.yaml b/platform/crd-ctrlr/src/config/samples/batch_v1alpha1_ipsecsite.yaml
new file mode 100644 (file)
index 0000000..7205625
--- /dev/null
@@ -0,0 +1,29 @@
+---
+apiVersion: batch.sdewan.akraino.org/v1alpha1
+kind: IpsecSite
+metadata:
+  name: ipsecsite
+  namespace: default
+  labels:
+    sdewanPurpose: cnf1
+spec:
+    name: siteA
+    type: "VTI-based"
+    remote: "%any"
+    pre_shared_key: test_key
+    authentication_method: psk
+    remote_identifier: host
+    local_identifier: Hub
+    crypto_proposal:
+      - ipsecproposal
+    force_crypto_proposal: "0"
+    connections:
+    - name: connA
+      conn_type: tunnel
+      mode: start
+      mark: "42"
+      remote_sourceip: "192.168.1.5-192.168.1.6"
+      local_subnet: 192.168.1.1/24,10.10.10.35/32
+      crypto_proposal:
+        - ipsecproposal
+...
index a22fda8..e45e878 100644 (file)
@@ -33,6 +33,7 @@ webhooks:
     - firewalldnats
     - ipsecproposals
     - ipsechosts
+    - ipsecsites
 - clientConfig:
     caBundle: Cg==
     service:
@@ -61,3 +62,4 @@ webhooks:
     - firewalldnats
     - ipsecproposals
     - ipsechosts
+    - ipsecsites
diff --git a/platform/crd-ctrlr/src/controllers/ipsecsite_controller.go b/platform/crd-ctrlr/src/controllers/ipsecsite_controller.go
new file mode 100644 (file)
index 0000000..64a2b56
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+
+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/builder"
+       "sigs.k8s.io/controller-runtime/pkg/client"
+       "sigs.k8s.io/controller-runtime/pkg/predicate"
+
+       batchv1alpha1 "sdewan.akraino.org/sdewan/api/v1alpha1"
+       "sdewan.akraino.org/sdewan/openwrt"
+)
+
+var ipsecSiteHandler = new(IpsecSiteHandler)
+
+type IpsecSiteHandler struct {
+}
+
+func (m *IpsecSiteHandler) GetType() string {
+       return "IpsecSite"
+}
+
+func (m *IpsecSiteHandler) GetName(instance runtime.Object) string {
+       site := instance.(*batchv1alpha1.IpsecSite)
+       return site.Name
+}
+
+func (m *IpsecSiteHandler) GetFinalizer() string {
+       return "ipsec.site.finalizers.sdewan.akraino.org"
+}
+
+func (m *IpsecSiteHandler) GetInstance(r client.Client, ctx context.Context, req ctrl.Request) (runtime.Object, error) {
+       instance := &batchv1alpha1.IpsecSite{}
+       err := r.Get(ctx, req.NamespacedName, instance)
+       return instance, err
+}
+
+func (m *IpsecSiteHandler) Convert(instance runtime.Object, deployment appsv1.Deployment) (openwrt.IOpenWrtObject, error) {
+       site := instance.(*batchv1alpha1.IpsecSite)
+       numOfConn := len(site.Spec.Connections)
+       conn := site.Spec.Connections
+       openwrtConn := make([]openwrt.SdewanIpsecConnection, numOfConn)
+       for i := 0; i < numOfConn; i++ {
+               openwrtConn[i] = openwrt.SdewanIpsecConnection{
+                       Name:           conn[i].Name,
+                       ConnType:       conn[i].ConnectionType,
+                       Mode:           conn[i].Mode,
+                       LocalSubnet:    conn[i].LocalSubnet,
+                       LocalUpdown:    conn[i].LocalUpDown,
+                       LocalFirewall:  conn[i].LocalFirewall,
+                       RemoteSubnet:   conn[i].RemoteSubnet,
+                       RemoteSourceip: conn[i].RemoteSourceIp,
+                       RemoteUpdown:   conn[i].RemoteUpDown,
+                       RemoteFirewall: conn[i].RemoteFirewall,
+                       CryptoProposal: conn[i].CryptoProposal,
+                       Mark:           conn[i].Mark,
+                       IfId:           conn[i].IfId,
+               }
+       }
+       siteObject := openwrt.SdewanIpsecRemote{
+               Name:                 site.Name,
+               Gateway:              site.Spec.Remote,
+               Type:                 site.Spec.Type,
+               AuthenticationMethod: site.Spec.AuthenticationMethod,
+               PreSharedKey:         site.Spec.PresharedKey,
+               LocalIdentifier:      site.Spec.LocalIdentifier,
+               RemoteIdentifier:     site.Spec.RemoteIdentifier,
+               CryptoProposal:       site.Spec.CryptoProposal,
+               ForceCryptoProposal:  site.Spec.ForceCryptoProposal,
+               LocalPublicCert:      site.Spec.LocalPublicCert,
+               LocalPrivateCert:     site.Spec.LocalPrivateCert,
+               SharedCa:             site.Spec.SharedCA,
+               Connections:          openwrtConn,
+       }
+       return &siteObject, nil
+}
+
+func (m *IpsecSiteHandler) IsEqual(instance1 openwrt.IOpenWrtObject, instance2 openwrt.IOpenWrtObject) bool {
+       site1 := instance1.(*openwrt.SdewanIpsecRemote)
+       site2 := instance2.(*openwrt.SdewanIpsecRemote)
+       return reflect.DeepEqual(*site1, *site2)
+}
+
+func (m *IpsecSiteHandler) GetObject(clientInfo *openwrt.OpenwrtClientInfo, name string) (openwrt.IOpenWrtObject, error) {
+       openwrtClient := openwrt.GetOpenwrtClient(*clientInfo)
+       ipsec := openwrt.IpsecClient{OpenwrtClient: openwrtClient}
+       ret, err := ipsec.GetRemote(name)
+       return ret, err
+}
+
+func (m *IpsecSiteHandler) CreateObject(clientInfo *openwrt.OpenwrtClientInfo, instance openwrt.IOpenWrtObject) (openwrt.IOpenWrtObject, error) {
+       openwrtClient := openwrt.GetOpenwrtClient(*clientInfo)
+       ipsec := openwrt.IpsecClient{OpenwrtClient: openwrtClient}
+       site := instance.(*openwrt.SdewanIpsecRemote)
+       return ipsec.CreateRemote(*site)
+}
+
+func (m *IpsecSiteHandler) UpdateObject(clientInfo *openwrt.OpenwrtClientInfo, instance openwrt.IOpenWrtObject) (openwrt.IOpenWrtObject, error) {
+       openwrtClient := openwrt.GetOpenwrtClient(*clientInfo)
+       ipsec := openwrt.IpsecClient{OpenwrtClient: openwrtClient}
+       site := instance.(*openwrt.SdewanIpsecRemote)
+       return ipsec.UpdateRemote(*site)
+}
+
+func (m *IpsecSiteHandler) DeleteObject(clientInfo *openwrt.OpenwrtClientInfo, name string) error {
+       openwrtClient := openwrt.GetOpenwrtClient(*clientInfo)
+       ipsec := openwrt.IpsecClient{OpenwrtClient: openwrtClient}
+       return ipsec.DeleteRemote(name)
+}
+
+func (m *IpsecSiteHandler) Restart(clientInfo *openwrt.OpenwrtClientInfo) (bool, error) {
+       openwrtClient := openwrt.GetOpenwrtClient(*clientInfo)
+       service := openwrt.ServiceClient{OpenwrtClient: openwrtClient}
+       return service.ExecuteService("ipsec", "restart")
+}
+
+// IpsecSiteReconciler reconciles a IpsecSite object
+type IpsecSiteReconciler struct {
+       client.Client
+       Log    logr.Logger
+       Scheme *runtime.Scheme
+}
+
+// +kubebuilder:rbac:groups=batch.sdewan.akraino.org,resources=ipsecsites,verbs=get;list;watch;create;update;patch;delete
+// +kubebuilder:rbac:groups=batch.sdewan.akraino.org,resources=ipsecsites/status,verbs=get;update;patch
+
+func (r *IpsecSiteReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
+       return ProcessReconcile(r, r.Log, req, ipsecSiteHandler)
+}
+
+func (r *IpsecSiteReconciler) SetupWithManager(mgr ctrl.Manager) error {
+       ps := builder.WithPredicates(predicate.GenerationChangedPredicate{})
+       return ctrl.NewControllerManagedBy(mgr).
+               For(&batchv1alpha1.IpsecSite{}, ps).
+               Complete(r)
+}
index 500a585..fd96072 100644 (file)
@@ -86,6 +86,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 0a5cc24..4709d16 100644 (file)
@@ -201,6 +201,14 @@ func main() {
                setupLog.Error(err, "unable to create webhook", "webhook", "CNFLabelWebhook")
                os.Exit(1)
        }
+       if err = (&controllers.IpsecSiteReconciler{
+               Client: mgr.GetClient(),
+               Log:    ctrl.Log.WithName("controllers").WithName("IpsecSite"),
+               Scheme: mgr.GetScheme(),
+       }).SetupWithManager(mgr); err != nil {
+               setupLog.Error(err, "unable to create controller", "controller", "IpsecSite")
+               os.Exit(1)
+       }
        // +kubebuilder:scaffold:builder
 
        setupLog.Info("starting manager")