From 903c79aff5ba97d631663f8d49a2b7bd4d51054d Mon Sep 17 00:00:00 2001 From: Jose Luis Vazquez Gonzalez Date: Wed, 31 Aug 2022 16:29:45 +0200 Subject: [PATCH] Make the controller main skinny --- cmd/controller/main.go | 261 +------------------- {cmd => pkg}/controller/controller.go | 2 +- {cmd => pkg}/controller/funcs.go | 2 +- {cmd => pkg}/controller/keyregistry.go | 2 +- {cmd => pkg}/controller/keyregistry_test.go | 2 +- {cmd => pkg}/controller/keys.go | 2 +- {cmd => pkg}/controller/keys_test.go | 2 +- pkg/controller/main.go | 248 +++++++++++++++++++ {cmd => pkg}/controller/main_test.go | 2 +- {cmd => pkg}/controller/metrics.go | 3 +- {cmd => pkg}/controller/server.go | 2 +- {cmd => pkg}/controller/server_test.go | 2 +- {cmd => pkg}/controller/signal_notwin.go | 2 +- {cmd => pkg}/controller/signal_windows.go | 2 +- 14 files changed, 269 insertions(+), 265 deletions(-) rename {cmd => pkg}/controller/controller.go (99%) rename {cmd => pkg}/controller/funcs.go (98%) rename {cmd => pkg}/controller/keyregistry.go (99%) rename {cmd => pkg}/controller/keyregistry_test.go (98%) rename {cmd => pkg}/controller/keys.go (99%) rename {cmd => pkg}/controller/keys_test.go (99%) create mode 100644 pkg/controller/main.go rename {cmd => pkg}/controller/main_test.go (99%) rename {cmd => pkg}/controller/metrics.go (99%) rename {cmd => pkg}/controller/server.go (99%) rename {cmd => pkg}/controller/server_test.go (98%) rename {cmd => pkg}/controller/signal_notwin.go (93%) rename {cmd => pkg}/controller/signal_windows.go (72%) diff --git a/cmd/controller/main.go b/cmd/controller/main.go index fa8921e501..100dbfab83 100644 --- a/cmd/controller/main.go +++ b/cmd/controller/main.go @@ -1,35 +1,16 @@ package main import ( - "context" - "crypto/rand" - "crypto/x509" goflag "flag" "fmt" - "io" "log" - "os" - "os/signal" - "sort" - "strings" - "syscall" "time" flag "github.com/spf13/pflag" - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/fields" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" - - "github.com/bitnami-labs/sealed-secrets/pkg/flagenv" - "github.com/bitnami-labs/sealed-secrets/pkg/pflagenv" ssv1alpha1 "github.com/bitnami-labs/sealed-secrets/pkg/apis/sealedsecrets/v1alpha1" "github.com/bitnami-labs/sealed-secrets/pkg/buildinfo" - sealedsecrets "github.com/bitnami-labs/sealed-secrets/pkg/client/clientset/versioned" - ssinformers "github.com/bitnami-labs/sealed-secrets/pkg/client/informers/externalversions" + "github.com/bitnami-labs/sealed-secrets/pkg/controller" ) const ( @@ -40,30 +21,9 @@ const ( var ( // VERSION set from Makefile VERSION = buildinfo.DefaultVersion - - // Selector used to find existing public/private key pairs on startup - keySelector = fields.OneTermEqualSelector(SealedSecretsKeyLabel, "active") ) -// Flags to configure the controller -type Flags struct { - KeyPrefix string - KeySize int - ValidFor time.Duration - MyCN string - KeyRenewPeriod time.Duration - AcceptV1Data bool - KeyCutoffTime string - NamespaceAll bool - AdditionalNamespaces string - LabelSelector string - RateLimitPerSecond int - RateLimitBurst int - OldGCBehavior bool - UpdateStatus bool -} - -func bindControllerFlags(f *Flags) { +func bindControllerFlags(f *controller.Flags) { flag.StringVar(&f.KeyPrefix, "key-prefix", "sealed-secrets-key", "Prefix used to name keys.") flag.IntVar(&f.KeySize, "key-size", 4096, "Size of encryption key.") flag.DurationVar(&f.ValidFor, "key-ttl", 10*365*24*time.Hour, "Duration that certificate is valid for.") @@ -80,229 +40,24 @@ func bindControllerFlags(f *Flags) { flag.BoolVar(&f.OldGCBehavior, "old-gc-behaviour", false, "Revert to old GC behavior where the controller deletes secrets instead of delegating that to k8s itself.") + flag.BoolVar(&f.UpdateStatus, "update-status", true, "beta: if true, the controller will update the status subresource whenever it processes a sealed secret") + flag.DurationVar(&f.KeyRenewPeriod, "rotate-period", defaultKeyRenewPeriod, "") _ = flag.CommandLine.MarkDeprecated("rotate-period", "please use key-renew-period instead") - - flag.BoolVar(&f.UpdateStatus, "update-status", true, "beta: if true, the controller will update the status subresource whenever it processes a sealed secret") } -func bindFlags(f *Flags, printVersion *bool) { +func bindFlags(f *controller.Flags, printVersion *bool) { buildinfo.FallbackVersion(&VERSION, buildinfo.DefaultVersion) flag.BoolVar(printVersion, "version", false, "Print version information and exit") bindControllerFlags(f) - flagenv.SetFlagsFromEnv(flagEnvPrefix, goflag.CommandLine) - pflagenv.SetFlagsFromEnv(flagEnvPrefix, flag.CommandLine) - - // Standard goflags (glog in particular) - flag.CommandLine.AddGoFlagSet(goflag.CommandLine) - if f := flag.CommandLine.Lookup("logtostderr"); f != nil { - f.DefValue = "true" - _ = f.Value.Set(f.DefValue) - } -} - -func initKeyPrefix(keyPrefix string) (string, error) { - return validateKeyPrefix(keyPrefix) -} - -func initKeyRegistry(ctx context.Context, client kubernetes.Interface, r io.Reader, namespace, prefix, label string, keysize int) (*KeyRegistry, error) { - log.Printf("Searching for existing private keys") - secretList, err := client.CoreV1().Secrets(namespace).List(ctx, metav1.ListOptions{ - LabelSelector: keySelector.String(), - }) - if err != nil { - return nil, err - } - items := secretList.Items - - s, err := client.CoreV1().Secrets(namespace).Get(ctx, prefix, metav1.GetOptions{}) - if !errors.IsNotFound(err) { - if err != nil { - return nil, err - } - items = append(items, *s) - // TODO(mkm): add the label to the legacy secret to simplify discovery and backups. - } - - keyRegistry := NewKeyRegistry(client, namespace, prefix, label, keysize) - sort.Sort(ssv1alpha1.ByCreationTimestamp(items)) - for _, secret := range items { - key, certs, err := readKey(secret) - if err != nil { - log.Printf("Error reading key %s: %v", secret.Name, err) - } - ct := secret.CreationTimestamp - if err := keyRegistry.registerNewKey(secret.Name, key, certs[0], ct.Time); err != nil { - return nil, err - } - log.Printf("----- %s", secret.Name) - } - return keyRegistry, nil -} - -func myNamespace() string { - if ns := os.Getenv("POD_NAMESPACE"); ns != "" { - return ns - } - - // Fall back to the namespace associated with the service account token, if available - if data, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace"); err == nil { - if ns := strings.TrimSpace(string(data)); len(ns) > 0 { - return ns - } - } - - return metav1.NamespaceDefault -} - -// Initialises the first key and starts the rotation job. returns an early trigger function. -// A period of 0 deactivates automatic rotation, but manual rotation (e.g. triggered by SIGUSR1) -// is still honoured. -func initKeyRenewal(ctx context.Context, registry *KeyRegistry, period, validFor time.Duration, cutoffTime time.Time, cn string) (func(), error) { - // Create a new key if it's the first key, - // or if it's older than cutoff time. - if len(registry.keys) == 0 || registry.mostRecentKey.creationTime.Before(cutoffTime) { - if _, err := registry.generateKey(ctx, validFor, cn); err != nil { - return nil, err - } - } - - // wrapper function to log error thrown by generateKey function - keyGenFunc := func() { - if _, err := registry.generateKey(ctx, validFor, cn); err != nil { - log.Printf("Failed to generate new key : %v\n", err) - } - } - if period == 0 { - return keyGenFunc, nil - } - - // If key rotation is enabled, we'll rotate the key when the most recent - // key becomes stale (older than period). - mostRecentKeyAge := time.Since(registry.mostRecentKey.creationTime) - initialDelay := period - mostRecentKeyAge - if initialDelay < 0 { - initialDelay = 0 - } - return ScheduleJobWithTrigger(initialDelay, period, keyGenFunc), nil -} - -func run(f *Flags, version string) error { - registerMetrics(version) - config, err := rest.InClusterConfig() - if err != nil { - return err - } - - clientset, err := kubernetes.NewForConfig(config) - if err != nil { - return err - } - - ssclientset, err := sealedsecrets.NewForConfig(config) - if err != nil { - return err - } - - myNs := myNamespace() - ctx := context.Background() - - prefix, err := initKeyPrefix(f.KeyPrefix) - if err != nil { - return err - } - - keyRegistry, err := initKeyRegistry(ctx, clientset, rand.Reader, myNs, prefix, SealedSecretsKeyLabel, f.KeySize) - if err != nil { - return err - } - - var ct time.Time - if f.KeyCutoffTime != "" { - var err error - ct, err = time.Parse(time.RFC1123Z, f.KeyCutoffTime) - if err != nil { - return err - } - } - - trigger, err := initKeyRenewal(ctx, keyRegistry, f.KeyRenewPeriod, f.ValidFor, ct, f.MyCN) - if err != nil { - return err - } - - initKeyGenSignalListener(trigger) - - namespace := v1.NamespaceAll - if !f.NamespaceAll || f.AdditionalNamespaces != "" { - namespace = myNamespace() - log.Printf("Starting informer for namespace: %s\n", namespace) - } - - var tweakopts func(*metav1.ListOptions) = nil - if f.LabelSelector != "" { - tweakopts = func(options *metav1.ListOptions) { - options.LabelSelector = f.LabelSelector - } - } - - ssinformer := ssinformers.NewFilteredSharedInformerFactory(ssclientset, 0, namespace, tweakopts) - controller := NewController(clientset, ssclientset, ssinformer, keyRegistry) - controller.oldGCBehavior = f.OldGCBehavior - controller.updateStatus = f.UpdateStatus - - stop := make(chan struct{}) - defer close(stop) - - go controller.Run(stop) - - if f.AdditionalNamespaces != "" { - addNS := removeDuplicates(strings.Split(f.AdditionalNamespaces, ",")) - - var inf ssinformers.SharedInformerFactory - var ctlr *Controller - - for _, ns := range addNS { - if _, err := clientset.CoreV1().Namespaces().Get(ctx, ns, metav1.GetOptions{}); err != nil { - if errors.IsNotFound(err) { - log.Printf("Warning: namespace '%s' doesn't exist\n", ns) - continue - } - return err - } - if ns != namespace { - inf = ssinformers.NewFilteredSharedInformerFactory(ssclientset, 0, ns, tweakopts) - ctlr = NewController(clientset, ssclientset, inf, keyRegistry) - ctlr.oldGCBehavior = f.OldGCBehavior - ctlr.updateStatus = f.UpdateStatus - log.Printf("Starting informer for namespace: %s\n", ns) - go ctlr.Run(stop) - } - } - } - - cp := func() ([]*x509.Certificate, error) { - cert, err := keyRegistry.getCert() - if err != nil { - return nil, err - } - return []*x509.Certificate{cert}, nil - } - - server := httpserver(cp, controller.AttemptUnseal, controller.Rotate, f.RateLimitBurst, f.RateLimitPerSecond) - - sigterm := make(chan os.Signal, 1) - signal.Notify(sigterm, syscall.SIGTERM) - <-sigterm - - return server.Shutdown(context.Background()) + flag.BoolVar(&f.UpdateStatus, "update-status", true, "beta: if true, the controller will update the status subresource whenever it processes a sealed secret") } func main() { + var flags controller.Flags var printVersion bool - var flags Flags bindFlags(&flags, &printVersion) flag.Parse() _ = goflag.CommandLine.Parse([]string{}) @@ -315,7 +70,7 @@ func main() { } log.Printf("Starting sealed-secrets controller version: %s\n", VERSION) - if err := run(&flags, VERSION); err != nil { + if err := controller.Main(&flags, VERSION); err != nil { panic(err.Error()) } } diff --git a/cmd/controller/controller.go b/pkg/controller/controller.go similarity index 99% rename from cmd/controller/controller.go rename to pkg/controller/controller.go index 9b6c6a3fb1..9573ffedb2 100644 --- a/cmd/controller/controller.go +++ b/pkg/controller/controller.go @@ -1,4 +1,4 @@ -package main +package controller import ( "context" diff --git a/cmd/controller/funcs.go b/pkg/controller/funcs.go similarity index 98% rename from cmd/controller/funcs.go rename to pkg/controller/funcs.go index fd634005f7..af6795369c 100644 --- a/cmd/controller/funcs.go +++ b/pkg/controller/funcs.go @@ -1,4 +1,4 @@ -package main +package controller import ( "fmt" diff --git a/cmd/controller/keyregistry.go b/pkg/controller/keyregistry.go similarity index 99% rename from cmd/controller/keyregistry.go rename to pkg/controller/keyregistry.go index 049a2493d8..5b53b8f9fa 100644 --- a/cmd/controller/keyregistry.go +++ b/pkg/controller/keyregistry.go @@ -1,4 +1,4 @@ -package main +package controller import ( "context" diff --git a/cmd/controller/keyregistry_test.go b/pkg/controller/keyregistry_test.go similarity index 98% rename from cmd/controller/keyregistry_test.go rename to pkg/controller/keyregistry_test.go index 1b002ae25d..85f62a3ef5 100644 --- a/cmd/controller/keyregistry_test.go +++ b/pkg/controller/keyregistry_test.go @@ -1,4 +1,4 @@ -package main +package controller import ( "testing" diff --git a/cmd/controller/keys.go b/pkg/controller/keys.go similarity index 99% rename from cmd/controller/keys.go rename to pkg/controller/keys.go index fe965ec231..bc50e596e2 100644 --- a/cmd/controller/keys.go +++ b/pkg/controller/keys.go @@ -1,4 +1,4 @@ -package main +package controller import ( "context" diff --git a/cmd/controller/keys_test.go b/pkg/controller/keys_test.go similarity index 99% rename from cmd/controller/keys_test.go rename to pkg/controller/keys_test.go index b1c31d03ae..5809a145e4 100644 --- a/cmd/controller/keys_test.go +++ b/pkg/controller/keys_test.go @@ -1,4 +1,4 @@ -package main +package controller import ( "context" diff --git a/pkg/controller/main.go b/pkg/controller/main.go new file mode 100644 index 0000000000..b89617a828 --- /dev/null +++ b/pkg/controller/main.go @@ -0,0 +1,248 @@ +package controller + +import ( + "context" + "crypto/rand" + "crypto/x509" + "io" + "log" + "os" + "os/signal" + "sort" + "strings" + "syscall" + "time" + + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + + ssv1alpha1 "github.com/bitnami-labs/sealed-secrets/pkg/apis/sealedsecrets/v1alpha1" + sealedsecrets "github.com/bitnami-labs/sealed-secrets/pkg/client/clientset/versioned" + ssinformers "github.com/bitnami-labs/sealed-secrets/pkg/client/informers/externalversions" +) + +// Flags to configure the controller +type Flags struct { + KeyPrefix string + KeySize int + ValidFor time.Duration + MyCN string + KeyRenewPeriod time.Duration + AcceptV1Data bool + KeyCutoffTime string + NamespaceAll bool + AdditionalNamespaces string + LabelSelector string + RateLimitPerSecond int + RateLimitBurst int + OldGCBehavior bool + UpdateStatus bool +} + +var ( + // Selector used to find existing public/private key pairs on startup + keySelector = fields.OneTermEqualSelector(SealedSecretsKeyLabel, "active") +) + +func initKeyPrefix(keyPrefix string) (string, error) { + return validateKeyPrefix(keyPrefix) +} + +func initKeyRegistry(ctx context.Context, client kubernetes.Interface, r io.Reader, namespace, prefix, label string, keysize int) (*KeyRegistry, error) { + log.Printf("Searching for existing private keys") + secretList, err := client.CoreV1().Secrets(namespace).List(ctx, metav1.ListOptions{ + LabelSelector: keySelector.String(), + }) + if err != nil { + return nil, err + } + items := secretList.Items + + s, err := client.CoreV1().Secrets(namespace).Get(ctx, prefix, metav1.GetOptions{}) + if !errors.IsNotFound(err) { + if err != nil { + return nil, err + } + items = append(items, *s) + // TODO(mkm): add the label to the legacy secret to simplify discovery and backups. + } + + keyRegistry := NewKeyRegistry(client, namespace, prefix, label, keysize) + sort.Sort(ssv1alpha1.ByCreationTimestamp(items)) + for _, secret := range items { + key, certs, err := readKey(secret) + if err != nil { + log.Printf("Error reading key %s: %v", secret.Name, err) + } + ct := secret.CreationTimestamp + if err := keyRegistry.registerNewKey(secret.Name, key, certs[0], ct.Time); err != nil { + return nil, err + } + log.Printf("----- %s", secret.Name) + } + return keyRegistry, nil +} + +func myNamespace() string { + if ns := os.Getenv("POD_NAMESPACE"); ns != "" { + return ns + } + + // Fall back to the namespace associated with the service account token, if available + if data, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace"); err == nil { + if ns := strings.TrimSpace(string(data)); len(ns) > 0 { + return ns + } + } + + return metav1.NamespaceDefault +} + +// Initialises the first key and starts the rotation job. returns an early trigger function. +// A period of 0 deactivates automatic rotation, but manual rotation (e.g. triggered by SIGUSR1) +// is still honoured. +func initKeyRenewal(ctx context.Context, registry *KeyRegistry, period time.Duration, cutoffTime time.Time) (func(), error) { + validFor := time.Hour + cn := "my-cn" + // Create a new key if it's the first key, + // or if it's older than cutoff time. + if len(registry.keys) == 0 || registry.mostRecentKey.creationTime.Before(cutoffTime) { + if _, err := registry.generateKey(ctx, validFor, cn); err != nil { + return nil, err + } + } + + // wrapper function to log error thrown by generateKey function + keyGenFunc := func() { + if _, err := registry.generateKey(ctx, validFor, cn); err != nil { + log.Printf("Failed to generate new key : %v\n", err) + } + } + if period == 0 { + return keyGenFunc, nil + } + + // If key rotation is enabled, we'll rotate the key when the most recent + // key becomes stale (older than period). + mostRecentKeyAge := time.Since(registry.mostRecentKey.creationTime) + initialDelay := period - mostRecentKeyAge + if initialDelay < 0 { + initialDelay = 0 + } + return ScheduleJobWithTrigger(initialDelay, period, keyGenFunc), nil +} + +func Main(f *Flags, version string) error { + registerMetrics(version) + config, err := rest.InClusterConfig() + if err != nil { + return err + } + + clientset, err := kubernetes.NewForConfig(config) + if err != nil { + return err + } + + ssclientset, err := sealedsecrets.NewForConfig(config) + if err != nil { + return err + } + + myNs := myNamespace() + ctx := context.Background() + + prefix, err := initKeyPrefix(f.KeyPrefix) + if err != nil { + return err + } + + keyRegistry, err := initKeyRegistry(ctx, clientset, rand.Reader, myNs, prefix, SealedSecretsKeyLabel, f.KeySize) + if err != nil { + return err + } + + var ct time.Time + if f.KeyCutoffTime != "" { + var err error + ct, err = time.Parse(time.RFC1123Z, f.KeyCutoffTime) + if err != nil { + return err + } + } + + trigger, err := initKeyRenewal(ctx, keyRegistry, f.KeyRenewPeriod, ct) + if err != nil { + return err + } + + initKeyGenSignalListener(trigger) + + namespace := v1.NamespaceAll + if !f.NamespaceAll || f.AdditionalNamespaces != "" { + namespace = myNamespace() + log.Printf("Starting informer for namespace: %s\n", namespace) + } + + var tweakopts func(*metav1.ListOptions) = nil + if f.LabelSelector != "" { + tweakopts = func(options *metav1.ListOptions) { + options.LabelSelector = f.LabelSelector + } + } + + ssinformer := ssinformers.NewFilteredSharedInformerFactory(ssclientset, 0, namespace, tweakopts) + controller := NewController(clientset, ssclientset, ssinformer, keyRegistry) + controller.oldGCBehavior = f.OldGCBehavior + controller.updateStatus = f.UpdateStatus + + stop := make(chan struct{}) + defer close(stop) + + go controller.Run(stop) + + if f.AdditionalNamespaces != "" { + addNS := removeDuplicates(strings.Split(f.AdditionalNamespaces, ",")) + + var inf ssinformers.SharedInformerFactory + var ctlr *Controller + + for _, ns := range addNS { + if _, err := clientset.CoreV1().Namespaces().Get(ctx, ns, metav1.GetOptions{}); err != nil { + if errors.IsNotFound(err) { + log.Printf("Warning: namespace '%s' doesn't exist\n", ns) + continue + } + return err + } + if ns != namespace { + inf = ssinformers.NewFilteredSharedInformerFactory(ssclientset, 0, ns, tweakopts) + ctlr = NewController(clientset, ssclientset, inf, keyRegistry) + ctlr.oldGCBehavior = f.OldGCBehavior + ctlr.updateStatus = f.UpdateStatus + log.Printf("Starting informer for namespace: %s\n", ns) + go ctlr.Run(stop) + } + } + } + + cp := func() ([]*x509.Certificate, error) { + cert, err := keyRegistry.getCert() + if err != nil { + return nil, err + } + return []*x509.Certificate{cert}, nil + } + + server := httpserver(cp, controller.AttemptUnseal, controller.Rotate, f.RateLimitBurst, f.RateLimitPerSecond) + + sigterm := make(chan os.Signal, 1) + signal.Notify(sigterm, syscall.SIGTERM) + <-sigterm + + return server.Shutdown(context.Background()) +} diff --git a/cmd/controller/main_test.go b/pkg/controller/main_test.go similarity index 99% rename from cmd/controller/main_test.go rename to pkg/controller/main_test.go index ae2d1b78b1..c2459e389b 100644 --- a/cmd/controller/main_test.go +++ b/pkg/controller/main_test.go @@ -1,4 +1,4 @@ -package main +package controller import ( "context" diff --git a/cmd/controller/metrics.go b/pkg/controller/metrics.go similarity index 99% rename from cmd/controller/metrics.go rename to pkg/controller/metrics.go index bcf509a448..129cc35d07 100644 --- a/cmd/controller/metrics.go +++ b/pkg/controller/metrics.go @@ -1,4 +1,4 @@ -package main +package controller import ( "net/http" @@ -28,6 +28,7 @@ var conditionStatusToGaugeValue = map[v1.ConditionStatus]float64{ // Define Prometheus metrics to expose var ( buildInfo prometheus.Gauge + // TODO: rename metric, change increment logic, or accept behaviour // when a SealedSecret is deleted the unseal() function is called which is // not technically an 'unseal request'. diff --git a/cmd/controller/server.go b/pkg/controller/server.go similarity index 99% rename from cmd/controller/server.go rename to pkg/controller/server.go index ac51930d65..fec44fa960 100644 --- a/cmd/controller/server.go +++ b/pkg/controller/server.go @@ -1,4 +1,4 @@ -package main +package controller import ( "crypto/x509" diff --git a/cmd/controller/server_test.go b/pkg/controller/server_test.go similarity index 98% rename from cmd/controller/server_test.go rename to pkg/controller/server_test.go index e7a577f34e..71552d66ec 100644 --- a/cmd/controller/server_test.go +++ b/pkg/controller/server_test.go @@ -1,4 +1,4 @@ -package main +package controller import ( "context" diff --git a/cmd/controller/signal_notwin.go b/pkg/controller/signal_notwin.go similarity index 93% rename from cmd/controller/signal_notwin.go rename to pkg/controller/signal_notwin.go index e1f99f4445..54566b0ff7 100644 --- a/cmd/controller/signal_notwin.go +++ b/pkg/controller/signal_notwin.go @@ -1,7 +1,7 @@ //go:build !windows // +build !windows -package main +package controller import ( "os" diff --git a/cmd/controller/signal_windows.go b/pkg/controller/signal_windows.go similarity index 72% rename from cmd/controller/signal_windows.go rename to pkg/controller/signal_windows.go index cf5512dd05..2f9d1a70c8 100644 --- a/cmd/controller/signal_windows.go +++ b/pkg/controller/signal_windows.go @@ -1,3 +1,3 @@ -package main +package controller func initKeyGenSignalListener(trigger func()) {}