diff --git a/.golangci.yaml b/.golangci.yaml index 25f2afbdcc..242c76e0da 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -10,6 +10,7 @@ linters: - errcheck - errchkjson #- errname + - errorlint #- gochecknoinits - gci #- goconst diff --git a/cmd/gitops-server/cmd/cmd.go b/cmd/gitops-server/cmd/cmd.go index 500a00af5e..8db3928100 100644 --- a/cmd/gitops-server/cmd/cmd.go +++ b/cmd/gitops-server/cmd/cmd.go @@ -368,7 +368,7 @@ func listenAndServe(log logr.Logger, srv *http.Server, options Options) error { if options.MTLS { caCert, err := os.ReadFile(options.TLSCertFile) if err != nil { - return fmt.Errorf("failed reading cert file %s. %s", options.TLSCertFile, err) + return fmt.Errorf("failed reading cert file %s. %w", options.TLSCertFile, err) } caCertPool := x509.NewCertPool() diff --git a/core/clustersmngr/factory.go b/core/clustersmngr/factory.go index 1c006436f5..4de8d877e7 100644 --- a/core/clustersmngr/factory.go +++ b/core/clustersmngr/factory.go @@ -314,7 +314,8 @@ func (cf *clustersManager) watchNamespaces(ctx context.Context) { if err := wait.PollUntilContextCancel(ctx, watchNamespaceFrequency, true, func(ctx context.Context) (bool, error) { if err := cf.UpdateNamespaces(ctx); err != nil { - if merr, ok := err.(*multierror.Error); ok { + var merr *multierror.Error + if errors.As(err, &merr) { for _, cerr := range merr.Errors { cf.log.Error(cerr, "failed to update namespaces") } @@ -349,9 +350,11 @@ func (cf *clustersManager) updateNamespacesWithClient(ctx context.Context, creat clientset, err := createClient() if err != nil { - if merr, ok := err.(*multierror.Error); ok { + var merr *multierror.Error + if errors.As(err, &merr) { for _, err := range merr.Errors { - if cerr, ok := err.(*ClientError); ok { + var cerr *ClientError + if errors.As(err, &cerr) { result = multierror.Append(result, fmt.Errorf("%w, cluster: %v", cerr, cerr.ClusterName)) } } diff --git a/core/server/fluxruntime.go b/core/server/fluxruntime.go index 0fb6a6a7f1..ed2b7cf6ff 100644 --- a/core/server/fluxruntime.go +++ b/core/server/fluxruntime.go @@ -82,9 +82,11 @@ func (cs *coreServer) ListRuntimeObjects(ctx context.Context, msg *pb.ListRuntim func listRuntimeObjectsByLabels(ctx context.Context, cs *coreServer, respErrors []*pb.ListError, labels []string) ([]*pb.ListError, []*pb.Deployment) { clustersClient, err := cs.clustersManager.GetImpersonatedClient(ctx, auth.Principal(ctx)) if err != nil { - if merr, ok := err.(*multierror.Error); ok { + var merr *multierror.Error + if errors.As(err, &merr) { for _, err := range merr.Errors { - if cerr, ok := err.(*clustersmngr.ClientError); ok { + var cerr *clustersmngr.ClientError + if errors.As(err, &cerr) { respErrors = append(respErrors, &pb.ListError{ClusterName: cerr.ClusterName, Message: cerr.Error()}) } } @@ -392,7 +394,7 @@ func (cs *coreServer) GetChildObjects(ctx context.Context, msg *pb.GetChildObjec }) if err := clustersClient.List(ctx, msg.ClusterName, &listResult, opts); err != nil { - return nil, fmt.Errorf("could not get unstructured object: %s", err) + return nil, fmt.Errorf("could not get unstructured object: %w", err) } respErrors := multierror.Error{} @@ -433,13 +435,13 @@ ItemsLoop: func sanitizeSecret(obj *unstructured.Unstructured) (client.Object, error) { bytes, err := obj.MarshalJSON() if err != nil { - return nil, fmt.Errorf("marshaling secret: %v", err) + return nil, fmt.Errorf("marshaling secret: %w", err) } s := &v1.Secret{} if err := json.Unmarshal(bytes, s); err != nil { - return nil, fmt.Errorf("unmarshaling secret: %v", err) + return nil, fmt.Errorf("unmarshaling secret: %w", err) } s.Data = map[string][]byte{"redacted": []byte(nil)} diff --git a/core/server/inventory.go b/core/server/inventory.go index ac4d106553..4a4188a76b 100644 --- a/core/server/inventory.go +++ b/core/server/inventory.go @@ -354,7 +354,7 @@ func getChildren(ctx context.Context, k8sClient client.Client, parentObj unstruc } if err := k8sClient.List(ctx, &listResult, client.InNamespace(parentObj.GetNamespace())); err != nil { - return nil, fmt.Errorf("could not get unstructured object: %s", err) + return nil, fmt.Errorf("could not get unstructured object: %w", err) } unstructuredChildren := []unstructured.Unstructured{} diff --git a/core/server/objects.go b/core/server/objects.go index f846c0b453..0f3cd1537a 100644 --- a/core/server/objects.go +++ b/core/server/objects.go @@ -58,9 +58,11 @@ func (cs *coreServer) ListObjects(ctx context.Context, msg *pb.ListObjectsReques } if err != nil { - if merr, ok := err.(*multierror.Error); ok { + var merr *multierror.Error + if errors.As(err, &merr) { for _, err := range merr.Errors { - if cerr, ok := err.(*clustersmngr.ClientError); ok { + var cerr *clustersmngr.ClientError + if errors.As(err, &cerr) { respErrors = append(respErrors, &pb.ListError{ClusterName: cerr.ClusterName, Message: cerr.Error()}) } } diff --git a/core/server/policies.go b/core/server/policies.go index d7d42244c2..ac1044433e 100644 --- a/core/server/policies.go +++ b/core/server/policies.go @@ -151,9 +151,11 @@ func (cs *coreServer) ListPolicies(ctx context.Context, m *pb.ListPoliciesReques clustersClient, err = cs.clustersManager.GetImpersonatedClient(ctx, auth.Principal(ctx)) if err != nil { - if merr, ok := err.(*multierror.Error); ok { + var merr *multierror.Error + if errors.As(err, &merr) { for _, err := range merr.Errors { - if cerr, ok := err.(*clustersmngr.ClientError); ok { + var cerr *clustersmngr.ClientError + if errors.As(err, &cerr) { respErrors = append(respErrors, &pb.ListError{ClusterName: cerr.ClusterName, Message: cerr.Error()}) } } diff --git a/core/server/policy_violations.go b/core/server/policy_violations.go index 5bfd6a8417..b4d1306a67 100644 --- a/core/server/policy_violations.go +++ b/core/server/policy_violations.go @@ -41,9 +41,11 @@ func (cs *coreServer) ListPolicyValidations(ctx context.Context, m *pb.ListPolic } if err != nil { - if merr, ok := err.(*multierror.Error); ok { + var merr *multierror.Error + if errors.As(err, &merr) { for _, err := range merr.Errors { - if cerr, ok := err.(*clustersmngr.ClientError); ok { + var cerr *clustersmngr.ClientError + if errors.As(err, &cerr) { respErrors = append(respErrors, &pb.ListError{ClusterName: cerr.ClusterName, Message: cerr.Error()}) } } @@ -62,7 +64,7 @@ func (cs *coreServer) ListPolicyValidations(ctx context.Context, m *pb.ListPolic "pac.weave.works/type": validationType, }) if err != nil { - return nil, fmt.Errorf("error building selector for events query: %v", err) + return nil, fmt.Errorf("error building selector for events query: %w", err) } fieldSelectorSet := map[string]string{ @@ -97,7 +99,7 @@ func (cs *coreServer) ListPolicyValidations(ctx context.Context, m *pb.ListPolic validationsList, err := cs.listValidationsFromEvents(ctx, clustersClient, m.ClusterName, false, opts) if err != nil { - return nil, fmt.Errorf("error getting events: %v", err) + return nil, fmt.Errorf("error getting events: %w", err) } respErrors = append(respErrors, validationsList.Errors...) policyviolationlist := pb.ListPolicyValidationsResponse{ @@ -136,7 +138,7 @@ func (cs *coreServer) GetPolicyValidation(ctx context.Context, m *pb.GetPolicyVa "pac.weave.works/id": m.ValidationId, }) if err != nil { - return nil, fmt.Errorf("error building selector for events query: %v", err) + return nil, fmt.Errorf("error building selector for events query: %w", err) } opts := []sigsClient.ListOption{} @@ -149,7 +151,7 @@ func (cs *coreServer) GetPolicyValidation(ctx context.Context, m *pb.GetPolicyVa validationsList, err := cs.listValidationsFromEvents(ctx, clusterClient, m.ClusterName, true, opts) if err != nil { - return nil, fmt.Errorf("error getting events: %v", err) + return nil, fmt.Errorf("error getting events: %w", err) } if len(validationsList.Errors) > 0 { return nil, fmt.Errorf("error getting events: %s", validationsList.Errors[0].Message) @@ -246,7 +248,7 @@ func getPolicyValidationParam(raw []byte) ([]*pb.PolicyValidationParam, error) { var paramsArr []map[string]interface{} err := json.Unmarshal(raw, ¶msArr) if err != nil { - return nil, fmt.Errorf("failed to unmarshal policy validation parameter, error: %v", err) + return nil, fmt.Errorf("failed to unmarshal policy validation parameter, error: %w", err) } parameters := make([]*pb.PolicyValidationParam, len(paramsArr)) diff --git a/pkg/fluxexec/exit_errors.go b/pkg/fluxexec/exit_errors.go index 57893d2a65..8e2933a6a0 100644 --- a/pkg/fluxexec/exit_errors.go +++ b/pkg/fluxexec/exit_errors.go @@ -2,14 +2,15 @@ package fluxexec import ( "context" + "errors" "fmt" "os/exec" "strings" ) func (flux *Flux) wrapExitError(ctx context.Context, err error, stderr string) error { - exitErr, ok := err.(*exec.ExitError) - if !ok { + var exitErr *exec.ExitError + if !errors.As(err, &exitErr) { // not an exit error, short circuit, nothing to wrap return err } diff --git a/pkg/fluxexec/fluxexec.go b/pkg/fluxexec/fluxexec.go index 3457e6c9a6..1befb81e13 100644 --- a/pkg/fluxexec/fluxexec.go +++ b/pkg/fluxexec/fluxexec.go @@ -23,7 +23,7 @@ func NewFlux(workingDir, execPath string) (*Flux, error) { } if _, err := os.Stat(workingDir); err != nil { - return nil, fmt.Errorf("error initialising Flux with workdir %s: %s", workingDir, err) + return nil, fmt.Errorf("error initialising Flux with workdir %s: %w", workingDir, err) } if execPath == "" { diff --git a/pkg/fluxinstall/errors/errors.go b/pkg/fluxinstall/errors/errors.go index 8d4f1d22d8..d95484442a 100644 --- a/pkg/fluxinstall/errors/errors.go +++ b/pkg/fluxinstall/errors/errors.go @@ -1,5 +1,7 @@ package errors +import "errors" + type skippableErr struct { Err error } @@ -13,6 +15,6 @@ func SkippableErr(err error) skippableErr { } func IsErrorSkippable(err error) bool { - _, ok := err.(skippableErr) - return ok + var skippableErr skippableErr + return errors.As(err, &skippableErr) } diff --git a/pkg/fluxinstall/installer.go b/pkg/fluxinstall/installer.go index 51d9b44776..2fed3dfe29 100644 --- a/pkg/fluxinstall/installer.go +++ b/pkg/fluxinstall/installer.go @@ -60,7 +60,7 @@ func (i *Installer) Ensure(ctx context.Context, sources ...src.Source) (string, } } - return "", fmt.Errorf("unable to find, or install from %d sources: %s", len(sources), errs.ErrorOrNil()) + return "", fmt.Errorf("unable to find, or install from %d sources: %w", len(sources), errs.ErrorOrNil()) } func (i *Installer) Install(ctx context.Context, sources ...src.Installable) (string, error) { @@ -86,7 +86,7 @@ func (i *Installer) Install(ctx context.Context, sources ...src.Installable) (st return execPath, nil } - return "", fmt.Errorf("unable install from %d sources: %s", len(sources), errs.ErrorOrNil()) + return "", fmt.Errorf("unable install from %d sources: %w", len(sources), errs.ErrorOrNil()) } func (i *Installer) Remove(ctx context.Context) error { diff --git a/pkg/gitproviders/provider.go b/pkg/gitproviders/provider.go index 105e88d28f..a2e5764bcd 100644 --- a/pkg/gitproviders/provider.go +++ b/pkg/gitproviders/provider.go @@ -85,7 +85,7 @@ func deployKeyExists(ctx context.Context, repo gitprovider.UserRepository) (bool if errors.Is(err, gitprovider.ErrNotFound) { return false, nil } else { - return false, fmt.Errorf("error getting deploy key %s: %s", DeployKeyName, err) + return false, fmt.Errorf("error getting deploy key %s: %w", DeployKeyName, err) } } else { return true, nil @@ -99,14 +99,14 @@ func uploadDeployKey(ctx context.Context, repo gitprovider.UserRepository, deplo return ErrRepositoryNoPermissionsOrDoesNotExist } - return fmt.Errorf("error uploading deploy key %s", err) + return fmt.Errorf("error uploading deploy key %w", err) } if err = utils.WaitUntil(os.Stdout, time.Second, defaultTimeout, func() error { _, err = repo.DeployKeys().Get(ctx, DeployKeyName) return err }); err != nil { - return fmt.Errorf("error verifying deploy key %s: %s", DeployKeyName, err) + return fmt.Errorf("error verifying deploy key %s: %w", DeployKeyName, err) } return nil @@ -163,7 +163,7 @@ func getCommits(ctx context.Context, repo gitprovider.UserRepository, targetBran return []gitprovider.Commit{}, nil } - return nil, fmt.Errorf("error getting commits: %s", err) + return nil, fmt.Errorf("error getting commits: %w", err) } return commits, nil @@ -183,7 +183,7 @@ func GetAccountType(provider gitprovider.Client, domain, owner string) (Provider return AccountTypeUser, nil } - return "", fmt.Errorf("could not get account type %s", err) + return "", fmt.Errorf("could not get account type %w", err) } return AccountTypeOrg, nil diff --git a/pkg/gitproviders/provider_org.go b/pkg/gitproviders/provider_org.go index c73dc84979..94552bb670 100644 --- a/pkg/gitproviders/provider_org.go +++ b/pkg/gitproviders/provider_org.go @@ -34,7 +34,7 @@ func (p orgGitProvider) RepositoryExists(ctx context.Context, repoURL RepoURL) ( func (p orgGitProvider) DeployKeyExists(ctx context.Context, repoURL RepoURL) (bool, error) { orgRepo, err := p.getOrgRepo(repoURL) if err != nil { - return false, fmt.Errorf("error getting org repo reference for owner %s, repo %s, %s", repoURL.Owner(), repoURL.RepositoryName(), err) + return false, fmt.Errorf("error getting org repo reference for owner %s, repo %s, %w", repoURL.Owner(), repoURL.RepositoryName(), err) } return deployKeyExists(ctx, orgRepo) diff --git a/pkg/http/server.go b/pkg/http/server.go index d94ce9f036..378ef58777 100644 --- a/pkg/http/server.go +++ b/pkg/http/server.go @@ -3,6 +3,7 @@ package http import ( "context" "crypto/tls" + "errors" "fmt" "log" "net" @@ -77,14 +78,14 @@ func startServer(ctx context.Context, hndlr http.Handler, listener net.Listener, logger.Printf("https://%s", srv.Addr) go func() { - if err := srv.Serve(listener); err != http.ErrServerClosed { + if err := srv.Serve(listener); !errors.Is(err, http.ErrServerClosed) { logger.Fatalf("server quit unexpectedly: %s", err) } }() <-ctx.Done() logger.Printf("shutting down %s", listener.Addr()) - if err := srv.Shutdown(ctx); err != nil && err != context.Canceled { + if err := srv.Shutdown(ctx); err != nil && !errors.Is(err, context.Canceled) { logger.Printf("error shutting down %s: %s", listener.Addr(), err) } } diff --git a/pkg/kube/kubehttp.go b/pkg/kube/kubehttp.go index 815e69463f..499abc5315 100644 --- a/pkg/kube/kubehttp.go +++ b/pkg/kube/kubehttp.go @@ -109,7 +109,7 @@ func NewKubeHTTPClient() (*KubeHTTP, error) { func RestConfig() (*rest.Config, string, error) { config, err := InClusterConfig() if err != nil { - if err == rest.ErrNotInCluster { + if errors.Is(err, rest.ErrNotInCluster) { return outOfClusterConfig() } // Handle other errors diff --git a/pkg/oidc/check/server.go b/pkg/oidc/check/server.go index 9be43a6b8c..6ba44c6355 100644 --- a/pkg/oidc/check/server.go +++ b/pkg/oidc/check/server.go @@ -88,7 +88,7 @@ func retrieveIDToken(log logger.Logger, oauth2Config oauth2.Config, verifier *oi }() if err := srv.Serve(listener); err != nil { - if err != http.ErrServerClosed { + if !errors.Is(err, http.ErrServerClosed) { return nil, fmt.Errorf("failed starting server: %w", err) } } diff --git a/pkg/run/utils.go b/pkg/run/utils.go index fd9aa9f798..5d2a1d852e 100644 --- a/pkg/run/utils.go +++ b/pkg/run/utils.go @@ -104,7 +104,7 @@ func GetPodFromResourceDescription(ctx context.Context, kubeClient client.Client case "service": svc := &corev1.Service{} if err := kubeClient.Get(ctx, namespacedName, svc); err != nil { - return nil, fmt.Errorf("error getting service: %s, namespaced Name: %v", err, namespacedName) + return nil, fmt.Errorf("error getting service: %w, namespaced Name: %v", err, namespacedName) } // list pods of the service "svc" by selector in a specific namespace using the controller-runtime client @@ -132,7 +132,7 @@ func GetPodFromResourceDescription(ctx context.Context, kubeClient client.Client case "deployment": deployment := &appsv1.Deployment{} if err := kubeClient.Get(ctx, namespacedName, deployment); err != nil { - return nil, fmt.Errorf("error getting deployment: %s, namespaced Name: %v", err, namespacedName) + return nil, fmt.Errorf("error getting deployment: %w, namespaced Name: %v", err, namespacedName) } // list pods of the deployment "deployment" by selector in a specific namespace using the controller-runtime client diff --git a/pkg/services/gitrepo/service.go b/pkg/services/gitrepo/service.go index b0b4c95ab9..950e7aa229 100644 --- a/pkg/services/gitrepo/service.go +++ b/pkg/services/gitrepo/service.go @@ -2,6 +2,7 @@ package gitrepo import ( "context" + "errors" "fmt" "os" @@ -17,7 +18,7 @@ func CommitAndPush(ctx context.Context, client git.Git, commitMsg string, logger Author: git.Author{Name: "Weave Gitops", Email: "weave-gitops@weave.works"}, Message: commitMsg, }, filters...) - if err != nil && err != git.ErrNoStagedFiles { + if err != nil && !errors.Is(err, git.ErrNoStagedFiles) { return fmt.Errorf("failed to update the repository: %w", err) } diff --git a/pkg/testutils/testutils.go b/pkg/testutils/testutils.go index 3b2d47b0ce..796b4f25bf 100644 --- a/pkg/testutils/testutils.go +++ b/pkg/testutils/testutils.go @@ -112,7 +112,7 @@ func StartK8sTestEnvironment(crdPaths []string) (*K8sTestEnv, error) { dc, err := discovery.NewDiscoveryClientForConfig(cfg) if err != nil { ctrlCancel() - return nil, fmt.Errorf("failed to initialize discovery client: %s", err) + return nil, fmt.Errorf("failed to initialize discovery client: %w", err) } mapper := restmapper.NewDeferredDiscoveryRESTMapper(memory.NewMemCacheClient(dc)) @@ -120,7 +120,7 @@ func StartK8sTestEnvironment(crdPaths []string) (*K8sTestEnv, error) { dyn, err := dynamic.NewForConfig(cfg) if err != nil { ctrlCancel() - return nil, fmt.Errorf("failed to initialize dynamic client: %s", err) + return nil, fmt.Errorf("failed to initialize dynamic client: %w", err) } k8sEnv = &K8sTestEnv{ diff --git a/pkg/utils/common.go b/pkg/utils/common.go index dae27dfcb4..91ae4aa3b4 100644 --- a/pkg/utils/common.go +++ b/pkg/utils/common.go @@ -2,6 +2,7 @@ package utils import ( "bytes" + "errors" "fmt" "io" "io/fs" @@ -122,7 +123,7 @@ func FindCoreConfig(dir string) WalkResult { for { var entry map[string]interface{} - if err := decoder.Decode(&entry); err == io.EOF { + if err := decoder.Decode(&entry); errors.Is(err, io.EOF) { break } @@ -159,7 +160,8 @@ func FindCoreConfig(dir string) WalkResult { return WalkResult{Status: Valid, Path: path} }) - if val, ok := err.(WalkResult); ok { + var val WalkResult + if errors.As(err, &val) { return val } diff --git a/pkg/validate/validate.go b/pkg/validate/validate.go index 626106cca7..371f4f34e9 100644 --- a/pkg/validate/validate.go +++ b/pkg/validate/validate.go @@ -4,6 +4,7 @@ import ( "archive/tar" "compress/gzip" "context" + "errors" "fmt" "io" "os" @@ -151,11 +152,11 @@ func Validate(log logger.Logger, targetDir, rootDir, kubernetesVersion, fluxVers var ( resourcesChan <-chan resource.Resource - errors <-chan error + errorsChan <-chan error ignoreFilenamePatterns []string ) - resourcesChan, errors = resource.FromFiles(ctx, files, ignoreFilenamePatterns) + resourcesChan, errorsChan = resource.FromFiles(ctx, files, ignoreFilenamePatterns) // Process discovered resources across multiple workers const numberOfWorkers = 4 @@ -177,15 +178,16 @@ func Validate(log logger.Logger, targetDir, rootDir, kubernetesVersion, fluxVers go func() { // Process errors while discovering resources - for err := range errors { + for err := range errorsChan { if err == nil { continue } - if err, ok := err.(resource.DiscoveryError); ok { + var derr resource.DiscoveryError + if errors.As(err, &derr) { validationResults <- validator.Result{ - Resource: resource.Resource{Path: err.Path}, - Err: err.Err, + Resource: resource.Resource{Path: derr.Path}, + Err: derr.Err, Status: validator.Error, } } else {