diff --git a/PROJECT b/PROJECT index 00cbc33..4c51971 100644 --- a/PROJECT +++ b/PROJECT @@ -19,4 +19,13 @@ resources: webhooks: defaulting: true webhookVersion: v1 +- api: + crdVersion: v1 + namespaced: true + controller: true + domain: kairos.io + group: entangle + kind: VPN + path: github.com/kairos-io/entangle/api/v1alpha1 + version: v1alpha1 version: "3" diff --git a/api/v1alpha1/vpn_types.go b/api/v1alpha1/vpn_types.go new file mode 100644 index 0000000..2b94ba4 --- /dev/null +++ b/api/v1alpha1/vpn_types.go @@ -0,0 +1,62 @@ +/* +Copyright 2022. + +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 ( + v1 "k8s.io/api/core/v1" + 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. + +// VPNSpec defines the desired state of VPN +type VPNSpec struct { + SecretRef *string `json:"secretRef,omitempty"` + Env []v1.EnvVar `json:"env,omitempty"` +} + +// VPNStatus defines the observed state of VPN +type VPNStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file +} + +//+kubebuilder:object:root=true +//+kubebuilder:subresource:status + +// VPN is the Schema for the vpns API +type VPN struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec VPNSpec `json:"spec,omitempty"` + Status VPNStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// VPNList contains a list of VPN +type VPNList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []VPN `json:"items"` +} + +func init() { + SchemeBuilder.Register(&VPN{}, &VPNList{}) +} diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index a9f63f8..1034cc7 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -136,3 +136,104 @@ func (in *EntanglementStatus) DeepCopy() *EntanglementStatus { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VPN) DeepCopyInto(out *VPN) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VPN. +func (in *VPN) DeepCopy() *VPN { + if in == nil { + return nil + } + out := new(VPN) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VPN) 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 *VPNList) DeepCopyInto(out *VPNList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VPN, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VPNList. +func (in *VPNList) DeepCopy() *VPNList { + if in == nil { + return nil + } + out := new(VPNList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VPNList) 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 *VPNSpec) DeepCopyInto(out *VPNSpec) { + *out = *in + if in.SecretRef != nil { + in, out := &in.SecretRef, &out.SecretRef + *out = new(string) + **out = **in + } + if in.Env != nil { + in, out := &in.Env, &out.Env + *out = make([]v1.EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VPNSpec. +func (in *VPNSpec) DeepCopy() *VPNSpec { + if in == nil { + return nil + } + out := new(VPNSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VPNStatus) DeepCopyInto(out *VPNStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VPNStatus. +func (in *VPNStatus) DeepCopy() *VPNStatus { + if in == nil { + return nil + } + out := new(VPNStatus) + in.DeepCopyInto(out) + return out +} diff --git a/config/crd/bases/entangle.kairos.io_vpns.yaml b/config/crd/bases/entangle.kairos.io_vpns.yaml new file mode 100644 index 0000000..e3f34d1 --- /dev/null +++ b/config/crd/bases/entangle.kairos.io_vpns.yaml @@ -0,0 +1,152 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.0 + creationTimestamp: null + name: vpns.entangle.kairos.io +spec: + group: entangle.kairos.io + names: + kind: VPN + listKind: VPNList + plural: vpns + singular: vpn + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: VPN is the Schema for the vpns 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: VPNSpec defines the desired state of VPN + properties: + env: + items: + description: EnvVar represents an environment variable present in + a Container. + properties: + name: + description: Name of the environment variable. Must be a C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded using + the previously defined environment variables in the container + and any service environment variables. If a variable cannot + be resolved, the reference in the input string will be unchanged. + Double $$ are reduced to a single $, which allows for escaping + the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will produce the + string literal "$(VAR_NAME)". Escaped references will never + be expanded, regardless of whether the variable exists or + not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. Cannot + be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key + must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, `metadata.annotations['''']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, + status.podIP, status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath is + written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the specified + API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the exposed + resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + secretRef: + type: string + type: object + status: + description: VPNStatus defines the observed state of VPN + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index b87d0f8..98035e1 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -3,17 +3,20 @@ # It should be run by config/default resources: - bases/entangle.kairos.io_entanglements.yaml +- bases/entangle.kairos.io_vpns.yaml #+kubebuilder:scaffold:crdkustomizeresource patchesStrategicMerge: # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. # patches here are for enabling the conversion webhook for each CRD #- patches/webhook_in_entanglements.yaml +#- patches/webhook_in_vpns.yaml #+kubebuilder:scaffold:crdkustomizewebhookpatch # [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix. # patches here are for enabling the CA injection for each CRD #- patches/cainjection_in_entanglements.yaml +#- patches/cainjection_in_vpns.yaml #+kubebuilder:scaffold:crdkustomizecainjectionpatch # the following config is for teaching kustomize how to do kustomization for CRDs. diff --git a/config/crd/patches/cainjection_in_vpns.yaml b/config/crd/patches/cainjection_in_vpns.yaml new file mode 100644 index 0000000..adeaca7 --- /dev/null +++ b/config/crd/patches/cainjection_in_vpns.yaml @@ -0,0 +1,7 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) + name: vpns.entangle.kairos.io diff --git a/config/crd/patches/webhook_in_vpns.yaml b/config/crd/patches/webhook_in_vpns.yaml new file mode 100644 index 0000000..b81e453 --- /dev/null +++ b/config/crd/patches/webhook_in_vpns.yaml @@ -0,0 +1,16 @@ +# The following patch enables a conversion webhook for the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: vpns.entangle.kairos.io +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + namespace: system + name: webhook-service + path: /convert + conversionReviewVersions: + - v1 diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 4292c9b..d8704f2 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -23,6 +23,18 @@ rules: - get - list - watch +- apiGroups: + - apps + resources: + - daemonsets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - apps resources: @@ -61,3 +73,29 @@ rules: - get - patch - update +- apiGroups: + - entangle.kairos.io + resources: + - vpns + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - entangle.kairos.io + resources: + - vpns/finalizers + verbs: + - update +- apiGroups: + - entangle.kairos.io + resources: + - vpns/status + verbs: + - get + - patch + - update diff --git a/config/rbac/vpn_editor_role.yaml b/config/rbac/vpn_editor_role.yaml new file mode 100644 index 0000000..ae1f750 --- /dev/null +++ b/config/rbac/vpn_editor_role.yaml @@ -0,0 +1,31 @@ +# permissions for end users to edit vpns. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: vpn-editor-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: entangle + app.kubernetes.io/part-of: entangle + app.kubernetes.io/managed-by: kustomize + name: vpn-editor-role +rules: +- apiGroups: + - entangle.kairos.io + resources: + - vpns + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - entangle.kairos.io + resources: + - vpns/status + verbs: + - get diff --git a/config/rbac/vpn_viewer_role.yaml b/config/rbac/vpn_viewer_role.yaml new file mode 100644 index 0000000..0bec95d --- /dev/null +++ b/config/rbac/vpn_viewer_role.yaml @@ -0,0 +1,27 @@ +# permissions for end users to view vpns. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: vpn-viewer-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: entangle + app.kubernetes.io/part-of: entangle + app.kubernetes.io/managed-by: kustomize + name: vpn-viewer-role +rules: +- apiGroups: + - entangle.kairos.io + resources: + - vpns + verbs: + - get + - list + - watch +- apiGroups: + - entangle.kairos.io + resources: + - vpns/status + verbs: + - get diff --git a/config/samples/entangle_v1alpha1_vpn.yaml b/config/samples/entangle_v1alpha1_vpn.yaml new file mode 100644 index 0000000..0dbc65b --- /dev/null +++ b/config/samples/entangle_v1alpha1_vpn.yaml @@ -0,0 +1,12 @@ +apiVersion: entangle.kairos.io/v1alpha1 +kind: VPN +metadata: + labels: + app.kubernetes.io/name: vpn + app.kubernetes.io/instance: vpn-sample + app.kubernetes.io/part-of: entangle + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: entangle + name: vpn-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml index 62c9ec6..15852a8 100644 --- a/config/samples/kustomization.yaml +++ b/config/samples/kustomization.yaml @@ -1,4 +1,5 @@ ## Append samples you want in your CSV to this file as resources ## resources: - entangle_v1alpha1_entanglement.yaml +- entangle_v1alpha1_vpn.yaml #+kubebuilder:scaffold:manifestskustomizesamples diff --git a/controllers/daemonset.go b/controllers/daemonset.go new file mode 100644 index 0000000..6670ea2 --- /dev/null +++ b/controllers/daemonset.go @@ -0,0 +1,87 @@ +package controllers + +import ( + entanglev1alpha1 "github.com/kairos-io/entangle/api/v1alpha1" + appsv1 "k8s.io/api/apps/v1" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +func genDaemonsetOwner(ent entanglev1alpha1.VPN) []metav1.OwnerReference { + return []metav1.OwnerReference{ + *metav1.NewControllerRef(&ent.ObjectMeta, schema.GroupVersionKind{ + Group: entanglev1alpha1.GroupVersion.Group, + Version: entanglev1alpha1.GroupVersion.Version, + Kind: "VPN", + }), + } +} + +func (r *VPNReconciler) genDaemonset(ent entanglev1alpha1.VPN) (*appsv1.DaemonSet, error) { + objMeta := metav1.ObjectMeta{ + Name: ent.Name, + Namespace: ent.Namespace, + OwnerReferences: genDaemonsetOwner(ent), + } + + privileged := true + serviceAccount := false + + v := ent.Spec.Env + v = append(v, v1.EnvVar{ + Name: "EDGEVPNTOKEN", + ValueFrom: &v1.EnvVarSource{ + SecretKeyRef: &v1.SecretKeySelector{ + Key: "network_token", + LocalObjectReference: v1.LocalObjectReference{ + Name: *ent.Spec.SecretRef, + }, + }, + }, + }) + + expose := v1.Container{ + SecurityContext: &v1.SecurityContext{ + Privileged: &privileged, + Capabilities: &v1.Capabilities{ + Add: []v1.Capability{"NET_ADMIN"}, + }, + }, + ImagePullPolicy: v1.PullAlways, + Name: "vpn", + Image: r.EntangleServiceImage, + Env: v, + Command: []string{"/usr/bin/edgevpn"}, + VolumeMounts: []v1.VolumeMount{v1.VolumeMount{Name: "dev-net-tun", MountPath: "/dev/net/tun"}}, + } + + pod := v1.PodSpec{ + Containers: []v1.Container{expose}, + AutomountServiceAccountToken: &serviceAccount, + HostNetwork: true, + Volumes: []v1.Volume{v1.Volume{Name: "dev-net-tun", VolumeSource: v1.VolumeSource{HostPath: &v1.HostPathVolumeSource{Path: "/dev/net/tun"}}}}, + } + + deploymentLabels := getnDaemonsetLabel(ent.Name) + + return &appsv1.DaemonSet{ + ObjectMeta: objMeta, + + Spec: appsv1.DaemonSetSpec{ + Selector: &metav1.LabelSelector{MatchLabels: deploymentLabels}, + Template: v1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: deploymentLabels, + }, + Spec: pod, + }, + }, + }, nil +} + +func getnDaemonsetLabel(s string) map[string]string { + return map[string]string{ + "vpn.kairos.io": s, + } +} diff --git a/controllers/entanglement_controller.go b/controllers/entanglement_controller.go index efcc130..252990f 100644 --- a/controllers/entanglement_controller.go +++ b/controllers/entanglement_controller.go @@ -70,7 +70,7 @@ func (r *EntanglementReconciler) Reconcile(ctx context.Context, req ctrl.Request return ctrl.Result{}, err } - desiredDeployment, err := r.genDeployment(ent,r.LogLevel) + desiredDeployment, err := r.genDeployment(ent, r.LogLevel) if err != nil { return ctrl.Result{}, err } diff --git a/controllers/vpn_controller.go b/controllers/vpn_controller.go new file mode 100644 index 0000000..5f5bc6b --- /dev/null +++ b/controllers/vpn_controller.go @@ -0,0 +1,114 @@ +/* +Copyright 2022. + +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" + "fmt" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + + entanglev1alpha1 "github.com/kairos-io/entangle/api/v1alpha1" +) + +// VPNReconciler reconciles a VPN object +type VPNReconciler struct { + client.Client + Scheme *runtime.Scheme + + clientSet *kubernetes.Clientset + EntangleServiceImage string +} + +//+kubebuilder:rbac:groups=entangle.kairos.io,resources=vpns,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=entangle.kairos.io,resources=vpns/status,verbs=get;update;patch +//+kubebuilder:rbac:groups=entangle.kairos.io,resources=vpns/finalizers,verbs=update +//+kubebuilder:rbac:groups=apps,resources=daemonsets,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups="",resources=secrets,verbs=create;get;list;watch + +// Reconcile is part of the main kubernetes reconciliation loop which aims to +// move the current state of the cluster closer to the desired state. +// TODO(user): Modify the Reconcile function to compare the state specified by +// the VPN object against the actual cluster state, and then +// perform operations to make the cluster state reflect the state specified by +// the user. +// +// For more details, check Reconcile and its Result here: +// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.13.0/pkg/reconcile +func (r *VPNReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + logger := log.FromContext(ctx) + + // Creates a deployment targeting a service + // TODO(user): your logic here + var ent entanglev1alpha1.VPN + if err := r.Get(ctx, req.NamespacedName, &ent); err != nil { + if apierrors.IsNotFound(err) { + return ctrl.Result{}, nil + } + return ctrl.Result{}, err + } + + desiredDaemonset, err := r.genDaemonset(ent) + if err != nil { + return ctrl.Result{}, err + } + + daemonset, err := r.clientSet.AppsV1().DaemonSets(req.Namespace).Get(ctx, desiredDaemonset.Name, v1.GetOptions{}) + if daemonset == nil || apierrors.IsNotFound(err) { + logger.Info(fmt.Sprintf("Creating Daemonset %v", daemonset)) + + daemonset, err = r.clientSet.AppsV1().DaemonSets(req.Namespace).Create(ctx, desiredDaemonset, v1.CreateOptions{}) + if err != nil { + logger.Error(err, "Failed while creating daemonset") + return ctrl.Result{}, nil + } + + return ctrl.Result{Requeue: true}, nil + } + if err != nil { + return ctrl.Result{Requeue: true}, err + } + + // // If args or env are missing, update it + // if desiredDaemonset.{ + // deployment, err = r.clientSet.AppsV1().Deployments(req.Namespace).Update(ctx, desiredDeployment, v1.UpdateOptions{}) + // if err != nil { + // logger.Error(err, "Failed while updating deployment") + // return ctrl.Result{}, nil + // } + // } + + return ctrl.Result{}, nil +} + +// SetupWithManager sets up the controller with the Manager. +func (r *VPNReconciler) SetupWithManager(mgr ctrl.Manager) error { + clientset, err := kubernetes.NewForConfig(mgr.GetConfig()) + if err != nil { + return err + } + r.clientSet = clientset + return ctrl.NewControllerManagedBy(mgr). + For(&entanglev1alpha1.VPN{}). + Complete(r) +} diff --git a/main.go b/main.go index c5f0557..b5b183a 100644 --- a/main.go +++ b/main.go @@ -118,6 +118,14 @@ func main() { os.Exit(1) } + if err = (&controllers.VPNReconciler{ + Client: mgr.GetClient(), + EntangleServiceImage: serviceImage, + Scheme: mgr.GetScheme(), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "VPN") + os.Exit(1) + } //+kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { diff --git a/tests/fixtures/vpn.yaml b/tests/fixtures/vpn.yaml new file mode 100644 index 0000000..92d8c06 --- /dev/null +++ b/tests/fixtures/vpn.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Secret +metadata: + name: mysecret + namespace: entangle-system +type: Opaque +stringData: + network_token: b3RwOgogIGRodDoKICAgIGludGVydmFsOiA5MDAwCiAgICBrZXk6IFVSRDVaMkcySDNKSFVESVpYT1VXQkVPN1VEU0g2TUpGUzJGV01QM1dBRVhaMjZRUTJGUkEKICAgIGxlbmd0aDogMzIKICBjcnlwdG86CiAgICBpbnRlcnZhbDogOTAwMAogICAga2V5OiBKTVJKWVZKN0xFR0lZQktFVFNERzVSRFhESkFKM0dTWVJOUTNUTVRQUkpMUkwzWEZYUVpBCiAgICBsZW5ndGg6IDMyCnJvb206IFJYWlZSNURCN1VWVERGRDc0UzRBTEFKNllHRVFDVlQ0WE5VWExFQTRVM0FDN05ESFFLTVEKcmVuZGV6dm91czogYk9PR21WV0lCV1ptbXBtaW9PcXdhc0dyWExlaXpnTVkKbWRuczogUnN4ZWd6eGZTcFlRRUtqQk1lUEFQelROWUV5ZGRlemEKbWF4X21lc3NhZ2Vfc2l6ZTogMjA5NzE1MjAK +--- +apiVersion: entangle.kairos.io/v1alpha1 +kind: VPN +metadata: + name: test2 + namespace: entangle-system +spec: + secretRef: "mysecret" \ No newline at end of file