diff --git a/.golangci.yml b/.golangci.yml index 65e2d4e..44bc5dc 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -7,14 +7,21 @@ linters-settings: list-mode: lax allow: - $gostd + - k8s.io/api + - k8s.io/apimachinery + - k8s.io/client-go - github.com/projectcapsule - github.com/go-logr/logr + - github.com/pkg/errors + - github.com/spf13/cobra - sigs.k8s.io/controller-runtime + funlen: + lines: 110 gci: sections: - standard # Captures all standard packages if they do not match another section. - default # Contains all imports that could not be matched to another section type. - - prefix(github.com/projectcapsule/capsule-addon-fluxcd) # Groups all imports with the specified Prefix. + - prefix(github.com/projectcapsule/capsule-addon-flux) # Groups all imports with the specified Prefix. goconst: min-len: 2 min-occurrences: 3 diff --git a/cmd/manager/manager.go b/cmd/manager/manager.go index ff96bc6..5d9b29f 100644 --- a/cmd/manager/manager.go +++ b/cmd/manager/manager.go @@ -6,6 +6,8 @@ package manager import ( "flag" "fmt" + "os" + "github.com/go-logr/logr" "github.com/pkg/errors" capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2" @@ -14,7 +16,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" - "os" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/healthz" @@ -59,6 +60,7 @@ func New() *cobra.Command { // Add Zap options. var fs flag.FlagSet + opts.Zo.BindFlags(&fs) cmd.Flags().AddGoFlagSet(&fs) @@ -70,6 +72,7 @@ func (o *Options) Run(_ *cobra.Command, _ []string) error { if err := clientgoscheme.AddToScheme(scheme); err != nil { return errors.Wrap(err, "unable to add client-go types to the manager's scheme") } + if err := capsulev1beta2.AddToScheme(scheme); err != nil { return errors.Wrap(err, "unable to add Capsule types to the manager's scheme") } @@ -90,6 +93,7 @@ func (o *Options) Run(_ *cobra.Command, _ []string) error { }) if err != nil { o.SetupLog.Error(err, "unable to create manager") + return errors.Wrap(err, "unable to create manager") } @@ -105,6 +109,7 @@ func (o *Options) Run(_ *cobra.Command, _ []string) error { if err = indexer.AddToManager(ctx, o.SetupLog, mgr); err != nil { o.SetupLog.Error(err, "unable to setup indexers") + return errors.Wrap(err, "unable to setup indexers") } @@ -115,11 +120,13 @@ func (o *Options) Run(_ *cobra.Command, _ []string) error { serviceaccount.WithProxyURL(o.ProxyURL), ).SetupWithManager(ctx, mgr); err != nil { o.SetupLog.Error(err, "unable to create manager", "controller", "ServiceAccount") + return errors.Wrap(err, "unable to setup the service account controller") } if err = mgr.Start(ctx); err != nil { o.SetupLog.Error(err, "problem running manager") + return errors.Wrap(err, "unable to start the manager") } diff --git a/cmd/root.go b/cmd/root.go index b3fd0ad..30579b1 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -4,8 +4,9 @@ package cmd import ( - "github.com/projectcapsule/capsule-addon-flux/cmd/manager" "github.com/spf13/cobra" + + "github.com/projectcapsule/capsule-addon-flux/cmd/manager" ) func New() *cobra.Command { @@ -20,5 +21,6 @@ func New() *cobra.Command { func Execute() error { cmd := New() + return cmd.Execute() } diff --git a/main.go b/main.go index 0c0051b..347101f 100644 --- a/main.go +++ b/main.go @@ -12,6 +12,7 @@ import ( func main() { if err := cmd.Execute(); err != nil { + //nolint:forbidigo fmt.Println(err) os.Exit(1) } diff --git a/pkg/controller/serviceaccount/globaltenantresources.go b/pkg/controller/serviceaccount/globaltenantresources.go index c9bf5b8..5ce10bf 100644 --- a/pkg/controller/serviceaccount/globaltenantresources.go +++ b/pkg/controller/serviceaccount/globaltenantresources.go @@ -5,6 +5,7 @@ package serviceaccount import ( "context" + capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" diff --git a/pkg/controller/serviceaccount/rolebindings.go b/pkg/controller/serviceaccount/rolebindings.go index a9d7f55..1050423 100644 --- a/pkg/controller/serviceaccount/rolebindings.go +++ b/pkg/controller/serviceaccount/rolebindings.go @@ -6,6 +6,7 @@ package serviceaccount import ( "context" "fmt" + rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" diff --git a/pkg/controller/serviceaccount/serviceaccount.go b/pkg/controller/serviceaccount/serviceaccount.go index faa783d..ea3e416 100644 --- a/pkg/controller/serviceaccount/serviceaccount.go +++ b/pkg/controller/serviceaccount/serviceaccount.go @@ -24,6 +24,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" ) +//nolint:revive type ServiceAccountReconciler struct { proxyURL string proxyCA string @@ -86,6 +87,7 @@ func (r *ServiceAccountReconciler) Reconcile(ctx context.Context, request ctrl.R return reconcile.Result{}, nil } + r.Log.Error(err, "Error reading the object") return ctrl.Result{}, err @@ -105,16 +107,15 @@ func (r *ServiceAccountReconciler) Reconcile(ctx context.Context, request ctrl.R if err != nil { return reconcile.Result{}, errors.Wrap(err, "error getting token of the service account") } + if tokenSecret.Data == nil { r.Log.Info("ServiceAccount token data is missing. Requeueing.") + return reconcile.Result{Requeue: true}, nil } // Build the kubeConfig for the ServiceAccount Tenant Owner. - config, err := r.buildKubeconfig(r.proxyURL, string(tokenSecret.Data[corev1.ServiceAccountTokenKey])) - if err != nil { - return reconcile.Result{}, errors.Wrap(err, "error building the tenant owner config") - } + config := r.buildKubeconfig(r.proxyURL, string(tokenSecret.Data[corev1.ServiceAccountTokenKey])) configRaw, err := clientcmd.Write(*config) if err != nil { @@ -145,10 +146,12 @@ func (r *ServiceAccountReconciler) Reconcile(ctx context.Context, request ctrl.R if sa.GetAnnotations()[ServiceAccountGlobalAnnotationKey] == ServiceAccountGlobalAnnotationValue { // Get the Tenant owned by the ServiceAccount. ownerName := fmt.Sprintf("system:serviceaccount:%s:%s", sa.GetNamespace(), sa.GetName()) + tenantList, err := r.listTenantsOwned(ctx, string(capsulev1beta2.ServiceAccountOwner), ownerName) if err != nil { return reconcile.Result{}, errors.Wrap(err, "error listing Tenants for owner") } + if tenantList.Items == nil { return reconcile.Result{}, errors.New("Tenant list for owner is empty") } @@ -179,6 +182,7 @@ func (r *ServiceAccountReconciler) forOption(ctx context.Context) builder.ForOpt predicate.NewPredicateFuncs(func(object client.Object) bool { ownerName := fmt.Sprintf("system:serviceaccount:%s:%s", object.GetNamespace(), object.GetName()) tntList, err := r.listTenantsOwned(ctx, string(capsulev1beta2.ServiceAccountOwner), ownerName) + return err == nil && tntList.Items != nil && len(tntList.Items) != 0 }), ), @@ -199,7 +203,7 @@ func (r *ServiceAccountReconciler) listTenantsOwned(ctx context.Context, ownerKi // buildKubeconfig returns a client-go/clientcmd/api.Config with a token and server URL specified as arguments. // The server set is be the proxy configured at ServiceAccountReconciler-level. -func (r *ServiceAccountReconciler) buildKubeconfig(server, token string) (*clientcmdapi.Config, error) { +func (r *ServiceAccountReconciler) buildKubeconfig(server, token string) *clientcmdapi.Config { // Build the client API Config. config := clientcmdapi.NewConfig() config.APIVersion = clientcmdlatest.Version @@ -231,5 +235,5 @@ func (r *ServiceAccountReconciler) buildKubeconfig(server, token string) (*clien config.Contexts = contexts config.CurrentContext = KubeconfigContextName - return config, nil + return config } diff --git a/pkg/controller/serviceaccount/tokens.go b/pkg/controller/serviceaccount/tokens.go index 4a95c77..c3d2099 100644 --- a/pkg/controller/serviceaccount/tokens.go +++ b/pkg/controller/serviceaccount/tokens.go @@ -8,7 +8,6 @@ import ( "fmt" "github.com/pkg/errors" - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" @@ -38,6 +37,7 @@ func (r *ServiceAccountReconciler) ensureSATokenSecret(ctx context.Context, name return nil } + return err } @@ -48,7 +48,6 @@ func (r *ServiceAccountReconciler) ensureSATokenSecret(ctx context.Context, name // are specified as arguments. func (r *ServiceAccountReconciler) getSATokenSecret(ctx context.Context, saName, saNamespace string) (*corev1.Secret, error) { saTokenList := new(corev1.SecretList) - // TODO: filter by Service Account-type and Namespace. Need index by Secret type. if err := r.Client.List(ctx, saTokenList); err != nil { return nil, ErrServiceAccountTokenNotFound } @@ -58,15 +57,16 @@ func (r *ServiceAccountReconciler) getSATokenSecret(ctx context.Context, saName, } var tokenSecret *corev1.Secret + for _, v := range saTokenList.Items { v := v - switch v.Type { - case corev1.SecretTypeServiceAccountToken: + if v.Type == corev1.SecretTypeServiceAccountToken { if v.Namespace == saNamespace && v.Annotations[corev1.ServiceAccountNameKey] == saName { return &v, nil } } } + if tokenSecret == nil { return nil, ErrServiceAccountTokenNotFound }