diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml deleted file mode 100644 index 0096d21c..00000000 --- a/.github/workflows/golangci-lint.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: golangci-lint -on: - push: - branches: - - main - pull_request: - -permissions: - contents: read - # pull-requests: read - checks: write - -jobs: - golangci: - name: lint - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 - with: - go-version: "1.22" - - name: golangci-lint - uses: golangci/golangci-lint-action@v6 - with: - version: latest - # only-new-issues: true - args: --timeout=5m diff --git a/CHANGELOG.md b/CHANGELOG.md index 29079c7c..8f0fe465 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,24 +1,3 @@ -## [2.6.1](https://github.com/jodevsa/wireguard-operator/compare/v2.6.0...v2.6.1) (2024-07-17) - - -### Bug Fixes - -* only add address as loadbalancerIP if svc type is LoadBalancer ([#203](https://github.com/jodevsa/wireguard-operator/issues/203)) ([56a609d](https://github.com/jodevsa/wireguard-operator/commit/56a609df561dd4d47509a6d6f406e4785a715890)) - -# [2.6.0](https://github.com/jodevsa/wireguard-operator/compare/v2.5.0...v2.6.0) (2024-07-17) - - -### Features - -* support ClusterIP service ([#201](https://github.com/jodevsa/wireguard-operator/issues/201)) ([a82d2bb](https://github.com/jodevsa/wireguard-operator/commit/a82d2bbeb26e5297d935d83556ba18f596878af8)) - -# [2.5.0](https://github.com/jodevsa/wireguard-operator/compare/v2.4.0...v2.5.0) (2024-07-15) - - -### Features - -* add golint support ([71150ea](https://github.com/jodevsa/wireguard-operator/commit/71150ea483dbf9f605d75fff86bc4dd91de92414)) - # [2.4.0](https://github.com/jodevsa/wireguard-operator/compare/v2.3.2...v2.4.0) (2024-07-15) diff --git a/README.md b/README.md index c51b0df0..64e82f81 100644 --- a/README.md +++ b/README.md @@ -83,12 +83,12 @@ Endpoint = 32.121.45.102:51820 ## How to deploy ``` -kubectl apply -f https://github.com/jodevsa/wireguard-operator/releases/download/v2.5.0/release.yaml +kubectl apply -f https://github.com/jodevsa/wireguard-operator/releases/download/v2.1.0/release.yaml ``` ## How to remove ``` -kubectl delete -f https://github.com/jodevsa/wireguard-operator/releases/download/v2.5.0/release.yaml +kubectl delete -f https://github.com/jodevsa/wireguard-operator/releases/download/v2.1.0/release.yaml ``` ## How to collaborate diff --git a/internal/it/suite_test.go b/internal/it/suite_test.go index f8c37ccd..50986808 100644 --- a/internal/it/suite_test.go +++ b/internal/it/suite_test.go @@ -60,7 +60,7 @@ func waitForDeploymentTobeReady(name string, namespace string) { } deployment := &v12.Deployment{} - Expect(k8sClient.Get(context.Background(), deploymentKey, deployment)).Should(Succeed()) + k8sClient.Get(context.Background(), deploymentKey, deployment) return int(deployment.Status.ReadyReplicas) }, Timeout, Interval).Should(Equal(1)) @@ -73,7 +73,7 @@ func WaitForWireguardToBeReady(name string, namespace string) { Name: name, } wg := &v1alpha1.Wireguard{} - Expect(k8sClient.Get(context.Background(), wgKey, wg)).Should(Succeed()) + k8sClient.Get(context.Background(), wgKey, wg) return wg.Status.Status }, Timeout, Interval).Should(Equal(v1alpha1.Ready)) @@ -86,7 +86,7 @@ func WaitForPeerToBeReady(name string, namespace string) { Name: name, } wg := &v1alpha1.WireguardPeer{} - Expect(k8sClient.Get(context.Background(), wgKey, wg)).Should(Succeed()) + k8sClient.Get(context.Background(), wgKey, wg) return wg.Status.Status }, Timeout, Interval).Should(Equal(v1alpha1.Ready)) @@ -228,7 +228,7 @@ var _ = BeforeSuite(func() { } deployment := &v12.Deployment{} - Expect(k8sClient.Get(context.Background(), deploymentKey, deployment)).Should(Succeed()) + k8sClient.Get(context.Background(), deploymentKey, deployment) return int(deployment.Status.ReadyReplicas) }, Timeout, Interval).Should(Equal(1)) diff --git a/pkg/agent/agent.go b/pkg/agent/agent.go index f79260bf..422ddff1 100644 --- a/pkg/agent/agent.go +++ b/pkg/agent/agent.go @@ -5,11 +5,11 @@ import ( "encoding/hex" "encoding/json" "fmt" + "github.com/go-logr/logr" "os" "path/filepath" "github.com/fsnotify/fsnotify" - "github.com/go-logr/logr" "github.com/jodevsa/wireguard-operator/pkg/api/v1alpha1" ) diff --git a/pkg/controllers/wireguard_controller.go b/pkg/controllers/wireguard_controller.go index e3c641c2..2476154c 100644 --- a/pkg/controllers/wireguard_controller.go +++ b/pkg/controllers/wireguard_controller.go @@ -58,18 +58,18 @@ func labelsForWireguard(name string) map[string]string { return map[string]string{"app": "wireguard", "instance": name} } -func (r *WireguardReconciler) ConfigmapForWireguard(m *v1alpha1.Wireguard, hostname string) (*corev1.ConfigMap, error) { +func (r *WireguardReconciler) ConfigmapForWireguard(m *v1alpha1.Wireguard, hostname string) *corev1.ConfigMap { + ls := labelsForWireguard(m.Name) dep := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: m.Name + "-config", Namespace: m.Namespace, - Labels: labelsForWireguard(m.Name), + Labels: ls, }, } - if err := ctrl.SetControllerReference(m, dep, r.Scheme); err != nil { - return nil, fmt.Errorf("set controller reference: %w", err) - } - return dep, nil + + ctrl.SetControllerReference(m, dep, r.Scheme) + return dep } func (r *WireguardReconciler) getWireguardPeers(ctx context.Context, req ctrl.Request) (*v1alpha1.WireguardPeerList, error) { @@ -311,11 +311,7 @@ func (r *WireguardReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( err = r.Get(ctx, types.NamespacedName{Name: wireguard.Name + "-metrics-svc", Namespace: wireguard.Namespace}, svcFound) if err != nil && errors.IsNotFound(err) { - svc, err := r.serviceForWireguardMetrics(wireguard) - if err != nil { - return ctrl.Result{}, fmt.Errorf("service for wireguard metrics: %w", err) - } - + svc := r.serviceForWireguardMetrics(wireguard) log.Info("Creating a new service", "service.Namespace", svc.Namespace, "service.Name", svc.Name) err = r.Create(ctx, svc) if err != nil { @@ -361,11 +357,7 @@ func (r *WireguardReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( err = r.Get(ctx, types.NamespacedName{Name: wireguard.Name + "-svc", Namespace: wireguard.Namespace}, svcFound) if err != nil && errors.IsNotFound(err) { - svc, err := r.serviceForWireguard(wireguard, serviceType) - if err != nil { - return ctrl.Result{}, fmt.Errorf("service for wireguard: %w", err) - } - + svc := r.serviceForWireguard(wireguard, serviceType) log.Info("Creating a new service", "service.Namespace", svc.Namespace, "service.Name", svc.Name) err = r.Create(ctx, svc) if err != nil { @@ -487,15 +479,10 @@ func (r *WireguardReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( if !bytes.Equal(b, secret.Data["state.json"]) { log.Info("Updating secret with new config") - publicKey := string(secret.Data["publicKey"]) - secret, err := r.secretForWireguard(wireguard, b, privateKey, publicKey) + err := r.Update(ctx, r.secretForWireguard(wireguard, b, privateKey, publicKey)) if err != nil { - return ctrl.Result{}, fmt.Errorf("secret for wireguard: %w", err) - } - - if err := r.Update(ctx, secret); err != nil { log.Error(err, "Failed to update secret with new config") return ctrl.Result{}, err } @@ -547,12 +534,7 @@ func (r *WireguardReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( return ctrl.Result{}, err } - bytes.Equal(b, secret.Data["state"]) - - secret, err := r.secretForWireguard(wireguard, b, privateKey, publicKey) - if err != nil { - return ctrl.Result{}, fmt.Errorf("secret for wireguard: %w", err) - } + secret := r.secretForWireguard(wireguard, b, privateKey, publicKey) log.Info("Creating a new secret", "secret.Namespace", secret.Namespace, "secret.Name", secret.Name) @@ -560,26 +542,6 @@ func (r *WireguardReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( log.Error(err, "Failed to create new secret", "secret.Namespace", secret.Namespace, "secret.Name", secret.Name) return ctrl.Result{}, err } - - clientKey, err := wgtypes.GeneratePrivateKey() - - if err != nil { - log.Error(err, "Failed to generate private key") - return ctrl.Result{}, err - } - - clientSecret, err := r.secretForClient(wireguard, clientKey.String(), clientKey.PublicKey().String()) - if err != nil { - return ctrl.Result{}, fmt.Errorf("secret for client: %w", err) - } - - log.Info("Creating a new secret", "secret.Namespace", clientSecret.Namespace, "secret.Name", clientSecret.Name) - err = r.Create(ctx, clientSecret) - if err != nil { - log.Error(err, "Failed to create new secret", "secret.Namespace", clientSecret.Namespace, "secret.Name", clientSecret.Name) - return ctrl.Result{}, err - } - return ctrl.Result{}, err } else if err != nil { log.Error(err, "Failed to get secret") @@ -591,14 +553,10 @@ func (r *WireguardReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( configFound := &corev1.ConfigMap{} err = r.Get(ctx, types.NamespacedName{Name: wireguard.Name + "-config", Namespace: wireguard.Namespace}, configFound) if err != nil && errors.IsNotFound(err) { - config, err := r.ConfigmapForWireguard(wireguard, address) - if err != nil { - return ctrl.Result{}, fmt.Errorf("config map for wireguard: %w", err) - } - + config := r.ConfigmapForWireguard(wireguard, address) log.Info("Creating a new config", "config.Namespace", config.Namespace, "config.Name", config.Name) - - if err := r.Create(ctx, config); err != nil { + err = r.Create(ctx, config) + if err != nil { log.Error(err, "Failed to create new dep", "dep.Namespace", config.Namespace, "dep.Name", config.Name) return ctrl.Result{}, err } @@ -616,11 +574,7 @@ func (r *WireguardReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( deploymentFound := &appsv1.Deployment{} err = r.Get(ctx, types.NamespacedName{Name: wireguard.Name + "-dep", Namespace: wireguard.Namespace}, deploymentFound) if err != nil && errors.IsNotFound(err) { - dep, err := r.deploymentForWireguard(wireguard) - if err != nil { - return ctrl.Result{}, fmt.Errorf("deployment for wireguard: %w", err) - } - + dep := r.deploymentForWireguard(wireguard) log.Info("Creating a new dep", "dep.Namespace", dep.Namespace, "dep.Name", dep.Name) err = r.Create(ctx, dep) if err != nil { @@ -635,12 +589,9 @@ func (r *WireguardReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( } if deploymentFound.Spec.Template.Spec.Containers[0].Image != r.AgentImage { - dep, err := r.deploymentForWireguard(wireguard) + dep := r.deploymentForWireguard(wireguard) + err = r.Update(ctx, dep) if err != nil { - return ctrl.Result{}, fmt.Errorf("deployment for wireguard: %w", err) - } - - if err := r.Update(ctx, dep); err != nil { log.Error(err, "unable to update deployment image", "dep.Namespace", dep.Namespace, "dep.Name", dep.Name) return ctrl.Result{}, err } @@ -673,10 +624,10 @@ func (r *WireguardReconciler) SetupWithManager(mgr ctrl.Manager) error { Complete(r) } -func (r *WireguardReconciler) serviceForWireguard(m *v1alpha1.Wireguard, serviceType corev1.ServiceType) (*corev1.Service, error) { +func (r *WireguardReconciler) serviceForWireguard(m *v1alpha1.Wireguard, serviceType corev1.ServiceType) *corev1.Service { labels := labelsForWireguard(m.Name) - svc := &corev1.Service{ + dep := &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ Name: m.Name + "-svc", Namespace: m.Namespace, @@ -695,20 +646,18 @@ func (r *WireguardReconciler) serviceForWireguard(m *v1alpha1.Wireguard, service }, } - if svc.Spec.Type == corev1.ServiceTypeLoadBalancer { - svc.Spec.LoadBalancerIP = m.Spec.Address + if dep.Spec.Type == corev1.ServiceTypeLoadBalancer { + dep.Spec.LoadBalancerIP = m.Spec.Address } - if err := ctrl.SetControllerReference(m, svc, r.Scheme); err != nil { - return nil, fmt.Errorf("set controller reference: %w", err) - } - return svc, nil + ctrl.SetControllerReference(m, dep, r.Scheme) + return dep } -func (r *WireguardReconciler) serviceForWireguardMetrics(m *v1alpha1.Wireguard) (*corev1.Service, error) { +func (r *WireguardReconciler) serviceForWireguardMetrics(m *v1alpha1.Wireguard) *corev1.Service { labels := labelsForWireguard(m.Name) - svc := &corev1.Service{ + dep := &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ Name: m.Name + "-metrics-svc", Namespace: m.Namespace, @@ -726,48 +675,29 @@ func (r *WireguardReconciler) serviceForWireguardMetrics(m *v1alpha1.Wireguard) }, } - if err := ctrl.SetControllerReference(m, svc, r.Scheme); err != nil { - return nil, fmt.Errorf("set controller reference: %w", err) - } - return svc, nil + ctrl.SetControllerReference(m, dep, r.Scheme) + return dep } -func (r *WireguardReconciler) secretForWireguard(m *v1alpha1.Wireguard, state []byte, privateKey string, publicKey string) (*corev1.Secret, error) { - secret := &corev1.Secret{ +func (r *WireguardReconciler) secretForWireguard(m *v1alpha1.Wireguard, state []byte, privateKey string, publicKey string) *corev1.Secret { + + ls := labelsForWireguard(m.Name) + dep := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: m.Name, Namespace: m.Namespace, - Labels: labelsForWireguard(m.Name), + Labels: ls, }, Data: map[string][]byte{"state.json": state, "privateKey": []byte(privateKey), "publicKey": []byte(publicKey)}, } - if err := ctrl.SetControllerReference(m, secret, r.Scheme); err != nil { - return nil, fmt.Errorf("set controller reference: %w", err) - } - - return secret, nil - -} - -func (r *WireguardReconciler) secretForClient(m *v1alpha1.Wireguard, privateKey string, publicKey string) (*corev1.Secret, error) { - secret := &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: m.Name + "-client", - Namespace: m.Namespace, - Labels: labelsForWireguard(m.Name), - }, - Data: map[string][]byte{"privateKey": []byte(privateKey), "publicKey": []byte(publicKey)}, - } + ctrl.SetControllerReference(m, dep, r.Scheme) - if err := ctrl.SetControllerReference(m, secret, r.Scheme); err != nil { - return nil, fmt.Errorf("set controller reference: %w", err) - } - return secret, nil + return dep } -func (r *WireguardReconciler) deploymentForWireguard(m *v1alpha1.Wireguard) (*appsv1.Deployment, error) { +func (r *WireguardReconciler) deploymentForWireguard(m *v1alpha1.Wireguard) *appsv1.Deployment { ls := labelsForWireguard(m.Name) replicas := int32(1) @@ -910,8 +840,6 @@ func (r *WireguardReconciler) deploymentForWireguard(m *v1alpha1.Wireguard) (*ap } } - if err := ctrl.SetControllerReference(m, dep, r.Scheme); err != nil { - return dep, fmt.Errorf("set controller reference: %w", err) - } - return dep, nil + ctrl.SetControllerReference(m, dep, r.Scheme) + return dep } diff --git a/pkg/controllers/wireguardpeer_controller.go b/pkg/controllers/wireguardpeer_controller.go index f18c6871..ec4a3be6 100644 --- a/pkg/controllers/wireguardpeer_controller.go +++ b/pkg/controllers/wireguardpeer_controller.go @@ -19,7 +19,6 @@ package controllers import ( "context" "fmt" - "github.com/jodevsa/wireguard-operator/pkg/api/v1alpha1" wgtypes "golang.zx2c4.com/wireguard/wgctrl/wgtypes" @@ -52,20 +51,20 @@ func (r *WireguardPeerReconciler) updateStatus(ctx context.Context, peer *v1alph return nil } -func (r *WireguardPeerReconciler) secretForPeer(m *v1alpha1.WireguardPeer, privateKey string, publicKey string) (*corev1.Secret, error) { - secret := &corev1.Secret{ +func (r *WireguardPeerReconciler) secretForPeer(m *v1alpha1.WireguardPeer, privateKey string, publicKey string) *corev1.Secret { + ls := labelsForWireguard(m.Name) + dep := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: m.Name + "-peer", Namespace: m.Namespace, - Labels: labelsForWireguard(m.Name), + Labels: ls, }, Data: map[string][]byte{"privateKey": []byte(privateKey), "publicKey": []byte(publicKey)}, } + // Set Nodered instance as the owner and controller + ctrl.SetControllerReference(m, dep, r.Scheme) - if err := ctrl.SetControllerReference(m, secret, r.Scheme); err != nil { - return nil, fmt.Errorf("set controller reference: %w", err) - } - return secret, nil + return dep } @@ -121,10 +120,7 @@ func (r *WireguardPeerReconciler) Reconcile(ctx context.Context, req ctrl.Reques privateKey := key.String() publicKey := key.PublicKey().String() - secret, err := r.secretForPeer(peer, privateKey, publicKey) - if err != nil { - return ctrl.Result{}, fmt.Errorf("secret for peer: %w", err) - } + secret := r.secretForPeer(peer, privateKey, publicKey) log.Info("Creating a new secret", "secret.Namespace", secret.Namespace, "secret.Name", secret.Name) err = r.Create(ctx, secret) @@ -179,25 +175,19 @@ func (r *WireguardPeerReconciler) Reconcile(ctx context.Context, req ctrl.Reques return ctrl.Result{}, nil } - var wireguardSecret corev1.Secret - if err := r.Get(ctx, types.NamespacedName{ - Name: newPeer.Spec.WireguardRef, - Namespace: newPeer.Namespace, - }, &wireguardSecret); err != nil { - return ctrl.Result{}, fmt.Errorf("get: %w", err) - } + wireguardSecret := &corev1.Secret{} + err = r.Get(ctx, types.NamespacedName{Name: newPeer.Spec.WireguardRef, Namespace: newPeer.Namespace}, wireguardSecret) if len(newPeer.OwnerReferences) == 0 { log.Info("Waiting for owner reference to be set " + wireguard.Name + " " + newPeer.Name) + ctrl.SetControllerReference(wireguard, newPeer, r.Scheme) - if err := ctrl.SetControllerReference(wireguard, newPeer, r.Scheme); err != nil { + if err != nil { log.Error(err, "Failed to update peer with controller reference") return ctrl.Result{}, err } - if err := r.Update(ctx, newPeer); err != nil { - return ctrl.Result{}, fmt.Errorf("update: %w", err) - } + r.Update(ctx, newPeer) return ctrl.Result{Requeue: true}, nil } diff --git a/pkg/wireguard/wireguard.go b/pkg/wireguard/wireguard.go index 9c55c041..c6407a01 100644 --- a/pkg/wireguard/wireguard.go +++ b/pkg/wireguard/wireguard.go @@ -7,6 +7,7 @@ import ( "syscall" "github.com/go-logr/logr" + "github.com/jodevsa/wireguard-operator/pkg/agent" "github.com/jodevsa/wireguard-operator/pkg/api/v1alpha1" "github.com/vishvananda/netlink" @@ -32,17 +33,17 @@ func syncRoute(_ agent.State, iface string) error { return nil } } - - if err := netlink.RouteAdd(&netlink.Route{ + route := netlink.Route{ LinkIndex: link.Attrs().Index, - Dst: &net.IPNet{ - IP: net.IP("10.8.0.0"), - Mask: net.IPMask("10.8.0.0/24"), - }, - Gw: net.ParseIP("10.8.0.1"), - }); err != nil { - return fmt.Errorf("netlink route add: %w", err) + Dst: &getIP("10.8.0.0/24")[0], + Gw: net.ParseIP("10.8.0.1"), } + + err = netlink.RouteAdd(&route) + if err != nil { + return err + } + return nil } @@ -158,10 +159,7 @@ func SyncLink(_ agent.State, iface string, wgUserspaceImplementationFallback str } if err := netlink.AddrAdd(link, &netlink.Addr{ - IPNet: &net.IPNet{ - IP: net.IP("10.8.0.1"), - Mask: net.IPMask("10.8.0.1/32"), - }, + IPNet: &getIP("10.8.0.1/32")[0], }); err != nil { return fmt.Errorf("netlink addr add: %w", err) } @@ -173,11 +171,7 @@ func SyncLink(_ agent.State, iface string, wgUserspaceImplementationFallback str } func (wg *Wireguard) syncWireguard(state agent.State, iface string, listenPort int) error { - c, err := wgctrl.New() - if err != nil { - return fmt.Errorf("new wgctrl client: %w", err) - } - + c, _ := wgctrl.New() cfg, err := CreateWireguardConfiguration(state, iface, listenPort) if err != nil { return err @@ -239,6 +233,12 @@ func (wg *Wireguard) Sync(state agent.State) error { return nil } +func getIP(ip string) []net.IPNet { + _, ipnet, _ := net.ParseCIDR(ip) + + return []net.IPNet{*ipnet} +} + func createPeersConfiguration(state agent.State, iface string) ([]wgtypes.PeerConfig, error) { var peersState = make(map[string]v1alpha1.WireguardPeer) for _, peer := range state.Peers { @@ -246,11 +246,13 @@ func createPeersConfiguration(state agent.State, iface string) ([]wgtypes.PeerCo } c, err := wgctrl.New() + if err != nil { return []wgtypes.PeerConfig{}, err } device, err := c.Device(iface) + if err != nil { return []wgtypes.PeerConfig{}, err } @@ -282,15 +284,10 @@ func createPeersConfiguration(state agent.State, iface string) ([]wgtypes.PeerCo } peerConfigurationByPublicKey[p.PublicKey.String()] = p } else if peer.AllowedIPs[0].IP.String() != peerState.Spec.Address { - _, n, err := net.ParseCIDR(peerState.Spec.Address + "/32") - if err != nil { - return nil, fmt.Errorf("parse cidr: %w", err) - } - // update peer p := wgtypes.PeerConfig{ UpdateOnly: true, - AllowedIPs: []net.IPNet{*n}, + AllowedIPs: getIP(peerState.Spec.Address + "/32"), PublicKey: peer.PublicKey, ReplaceAllowedIPs: true, } @@ -321,14 +318,9 @@ func createPeersConfiguration(state agent.State, iface string) ([]wgtypes.PeerCo continue } - _, n, err := net.ParseCIDR(peer.Spec.Address + "/32") - if err != nil { - return nil, fmt.Errorf("parse cidr: %w", err) - } - // create peer p := wgtypes.PeerConfig{ - AllowedIPs: []net.IPNet{*n}, + AllowedIPs: getIP(peer.Spec.Address + "/32"), PublicKey: key, } peerConfigurationByPublicKey[p.PublicKey.String()] = p