diff --git a/docker/postgres-kanister-tools/requirements.txt b/docker/postgres-kanister-tools/requirements.txt index 9887c7d51b..e1e713f440 100644 --- a/docker/postgres-kanister-tools/requirements.txt +++ b/docker/postgres-kanister-tools/requirements.txt @@ -1,4 +1,4 @@ -awscli==1.35.20 +awscli==1.36.10 pip==24.3.1 -setuptools==75.3.0 -wheel==0.44.0 +setuptools==75.6.0 +wheel==0.45.1 diff --git a/docker/postgresql/requirements.txt b/docker/postgresql/requirements.txt index 5bfbb11d44..fdc1cfa954 100644 --- a/docker/postgresql/requirements.txt +++ b/docker/postgresql/requirements.txt @@ -1,5 +1,5 @@ -awscli==1.35.20 +awscli==1.36.10 wal-e==1.1.1 pip==24.3.1 -setuptools==75.3.0 -wheel==0.44.0 +setuptools==75.6.0 +wheel==0.45.1 diff --git a/pkg/apis/cr/v1alpha1/repositoryserver_types_test.go b/pkg/apis/cr/v1alpha1/repositoryserver_types_test.go index 0e051742f1..524d8328c5 100644 --- a/pkg/apis/cr/v1alpha1/repositoryserver_types_test.go +++ b/pkg/apis/cr/v1alpha1/repositoryserver_types_test.go @@ -17,7 +17,7 @@ package v1alpha1 import ( "testing" - "github.com/pkg/errors" + "github.com/kanisterio/errkit" "gopkg.in/check.v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/serializer" @@ -86,7 +86,7 @@ func getRepositoryServerFromSpec(spec []byte) (*RepositoryServer, error) { repositoryServer := &RepositoryServer{} d := serializer.NewCodecFactory(runtime.NewScheme()).UniversalDeserializer() if _, _, err := d.Decode([]byte(spec), nil, repositoryServer); err != nil { - return nil, errors.Wrap(err, "Failed to decode RepositoryServer") + return nil, errkit.Wrap(err, "Failed to decode RepositoryServer") } return repositoryServer, nil } diff --git a/pkg/apis/cr/v1alpha1/types_test.go b/pkg/apis/cr/v1alpha1/types_test.go index 6da1bc3d7d..6518183101 100644 --- a/pkg/apis/cr/v1alpha1/types_test.go +++ b/pkg/apis/cr/v1alpha1/types_test.go @@ -18,7 +18,7 @@ import ( "reflect" "testing" - "github.com/pkg/errors" + "github.com/kanisterio/errkit" "gopkg.in/check.v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/serializer" @@ -73,7 +73,7 @@ func getBlueprintFromSpec(spec []byte) (*Blueprint, error) { blueprint := &Blueprint{} d := serializer.NewCodecFactory(runtime.NewScheme()).UniversalDeserializer() if _, _, err := d.Decode([]byte(spec), nil, blueprint); err != nil { - return nil, errors.Wrap(err, "Failed to decode spec into object") + return nil, errkit.Wrap(err, "Failed to decode spec into object") } return blueprint, nil } diff --git a/pkg/blockstorage/azure/azuredisk.go b/pkg/blockstorage/azure/azuredisk.go index 24ffe5cb09..e67d6ef07a 100644 --- a/pkg/blockstorage/azure/azuredisk.go +++ b/pkg/blockstorage/azure/azuredisk.go @@ -549,12 +549,12 @@ func (s *AdStorage) SnapshotsList(ctx context.Context, tags map[string]string) ( return nil, errkit.Wrap(err, "SnapshotsClient.List in SnapshotsList") } for _, snap := range page.Value { - k10Snap, err := s.SnapshotParse(ctx, *snap) + parsedSnap, err := s.SnapshotParse(ctx, *snap) if err != nil { log.WithError(err).Print("Incorrect Snaphost type", field.M{"SnapshotID": snap.ID}) continue } - snaps = append(snaps, k10Snap) + snaps = append(snaps, parsedSnap) } } snaps = blockstorage.FilterSnapshotsWithTags(snaps, blockstorage.SanitizeTags(tags)) diff --git a/pkg/blockstorage/tags/tags.go b/pkg/blockstorage/tags/tags.go index ae99e2eec0..95dbb3faea 100644 --- a/pkg/blockstorage/tags/tags.go +++ b/pkg/blockstorage/tags/tags.go @@ -27,7 +27,7 @@ import ( const ( // ClusterTagKey is used to tag resources with the cluster name ClusterTagKey = "kanister.io/clustername" - // VersionTagKey is used to tag resources with the K10 version + // VersionTagKey is used to tag resources with a version VersionTagKey = "kanister.io/version" // AppNameTag is used to tag volumes with the app they belong to AppNameTag = "kanister.io/appname" diff --git a/pkg/errorchecker/errorchecker_test.go b/pkg/errorchecker/errorchecker_test.go index 3a12e5a5ef..f8466a3c14 100644 --- a/pkg/errorchecker/errorchecker_test.go +++ b/pkg/errorchecker/errorchecker_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/kanisterio/errkit" - "github.com/pkg/errors" "gopkg.in/check.v1" ) @@ -18,11 +17,11 @@ var _ = check.Suite(&ErrorsTestSuite{}) func (ts *ErrorsTestSuite) TestWrappingAndMatching(c *check.C) { errkitErr := errkit.New("Errkit error") errkitWrappedErr := errkit.Wrap(errkitErr, "errkit wrapped") - errorsWrappedErr := errors.Wrap(errkitWrappedErr, "errors wrapped") - errorsWrappedErr1 := errors.Wrap(errorsWrappedErr, "errors wrapped 1") + errorsWrappedErr := errkit.Wrap(errkitWrappedErr, "errors wrapped") + errorsWrappedErr1 := errkit.Wrap(errorsWrappedErr, "errors wrapped 1") // Ensure that errors from 'errkit' wrapped by the older 'errors' package remain matchable. - c.Assert(errors.Is(errorsWrappedErr, errkitErr), check.Equals, true) + c.Assert(errkit.Is(errorsWrappedErr, errkitErr), check.Equals, true) // Ensure that transformation to string still works c.Assert(errorsWrappedErr1.Error(), check.Equals, "errors wrapped 1: errors wrapped: errkit wrapped: Errkit error") // Ensure that error message matching does work as expected diff --git a/pkg/function/export_rds_snapshot_location.go b/pkg/function/export_rds_snapshot_location.go index c2df143550..ca32c18251 100644 --- a/pkg/function/export_rds_snapshot_location.go +++ b/pkg/function/export_rds_snapshot_location.go @@ -18,6 +18,7 @@ import ( "context" "encoding/json" "fmt" + "strconv" "strings" "time" @@ -435,6 +436,8 @@ func postgresBackupCommand(dbEndpoint, username, password string, dbList []strin return nil, errkit.New("No database found to backup") } + profileQuoted := strconv.Quote(string(profile)) + command := []string{ "bash", "-o", @@ -452,9 +455,9 @@ func postgresBackupCommand(dbEndpoint, username, password string, dbList []strin for db in "${dblist[@]}"; do echo "backing up $db db" && pg_dump $db -C --inserts > /backup/$db.sql; done - tar -zc backup | kando location push --profile '%s' --path "${BACKUP_PREFIX}/${BACKUP_ID}" - + tar -zc backup | kando location push --profile %s --path "${BACKUP_PREFIX}/${BACKUP_ID}" - kando output %s ${BACKUP_ID}`, - dbEndpoint, backupPrefix, backupID, strings.Join(dbList, " "), profile, ExportRDSSnapshotToLocBackupID), + dbEndpoint, backupPrefix, backupID, strings.Join(dbList, " "), profileQuoted, ExportRDSSnapshotToLocBackupID), } return command, nil } diff --git a/pkg/function/rds_functions_test.go b/pkg/function/rds_functions_test.go index fc037e6749..f278369a05 100644 --- a/pkg/function/rds_functions_test.go +++ b/pkg/function/rds_functions_test.go @@ -60,10 +60,32 @@ func (s *RDSFunctionsTest) TestPrepareCommand(c *check.C) { command: []string{"bash", "-o", "errexit", "-o", "pipefail", "-c", fmt.Sprintf(` export PGHOST=%s - kando location pull --profile '%s' --path "%s" - | gunzip -c -f | sed 's/"LOCALE"/"LC_COLLATE"/' | psql -q -U "${PGUSER}" %s + kando location pull --profile "%s" --path "%s" - | gunzip -c -f | sed 's/"LOCALE"/"LC_COLLATE"/' | psql -q -U "${PGUSER}" %s `, "db-endpoint", "null", fmt.Sprintf("%s/%s", "/backup/postgres-backup", "backup-id"), postgres.DefaultConnectDatabase), }, }, + { + name: "PostgreS restore command with profile", + dbEngine: PostgrSQLEngine, + action: RestoreAction, + dbEndpoint: "db-endpoint", + username: "test-user", + password: "secret-pass", + backupPrefix: "/backup/postgres-backup", + backupID: "backup-id", + dbEngineVersion: "12.7", + errChecker: check.IsNil, + dbList: []string{"template1"}, + command: []string{"bash", "-o", "errexit", "-o", "pipefail", "-c", + fmt.Sprintf(` + export PGHOST=%s + kando location pull --profile "{\"Location\":{\"type\":\"\",\"bucket\":\"\",\"endpoint\":\"\",\"prefix\":\"\",\"region\":\"\"},\"Credential\":{\"Type\":\"\",\"KeyPair\":null,\"Secret\":null,\"KopiaServerSecret\":null},\"SkipSSLVerify\":false}" --path "%s" - | gunzip -c -f | sed 's/"LOCALE"/"LC_COLLATE"/' | psql -q -U "${PGUSER}" %s + `, "db-endpoint", fmt.Sprintf("%s/%s", "/backup/postgres-backup", "backup-id"), postgres.DefaultConnectDatabase), + }, + tp: param.TemplateParams{ + Profile: ¶m.Profile{}, + }, + }, { name: "PostgreS restore command", dbEngine: PostgrSQLEngine, @@ -79,7 +101,7 @@ func (s *RDSFunctionsTest) TestPrepareCommand(c *check.C) { command: []string{"bash", "-o", "errexit", "-o", "pipefail", "-c", fmt.Sprintf(` export PGHOST=%s - kando location pull --profile '%s' --path "%s" - | gunzip -c -f | psql -q -U "${PGUSER}" %s + kando location pull --profile "%s" --path "%s" - | gunzip -c -f | psql -q -U "${PGUSER}" %s `, "db-endpoint", "null", fmt.Sprintf("%s/%s", "/backup/postgres-backup", "backup-id"), postgres.DefaultConnectDatabase), }, }, @@ -106,7 +128,7 @@ func (s *RDSFunctionsTest) TestPrepareCommand(c *check.C) { for db in "${dblist[@]}"; do echo "backing up $db db" && pg_dump $db -C --inserts > /backup/$db.sql; done - tar -zc backup | kando location push --profile '%s' --path "${BACKUP_PREFIX}/${BACKUP_ID}" - + tar -zc backup | kando location push --profile "%s" --path "${BACKUP_PREFIX}/${BACKUP_ID}" - kando output %s ${BACKUP_ID}`, "db-endpoint", "/backup/postgres-backup", "backup-id", strings.Join([]string{"template1"}, " "), "null", ExportRDSSnapshotToLocBackupID), }, diff --git a/pkg/function/restore_rds_snapshot.go b/pkg/function/restore_rds_snapshot.go index df5dd16957..76f482bfdd 100644 --- a/pkg/function/restore_rds_snapshot.go +++ b/pkg/function/restore_rds_snapshot.go @@ -17,6 +17,7 @@ package function import ( "context" "fmt" + "strconv" "time" "github.com/aws/aws-sdk-go/aws" @@ -335,6 +336,8 @@ func postgresRestoreCommand(pgHost, username, password string, backupArtifactPre replaceCommand = ` sed 's/"LOCALE"/"LC_COLLATE"/' |` } + profileQuoted := strconv.Quote(string(profile)) + return []string{ "bash", "-o", @@ -344,8 +347,8 @@ func postgresRestoreCommand(pgHost, username, password string, backupArtifactPre "-c", fmt.Sprintf(` export PGHOST=%s - kando location pull --profile '%s' --path "%s" - | gunzip -c -f |%s psql -q -U "${PGUSER}" %s - `, pgHost, profile, fmt.Sprintf("%s/%s", backupArtifactPrefix, backupID), replaceCommand, postgres.DefaultConnectDatabase), + kando location pull --profile %s --path "%s" - | gunzip -c -f |%s psql -q -U "${PGUSER}" %s + `, pgHost, profileQuoted, fmt.Sprintf("%s/%s", backupArtifactPrefix, backupID), replaceCommand, postgres.DefaultConnectDatabase), }, nil } diff --git a/pkg/kube/exec_test.go b/pkg/kube/exec_test.go index 9242abb4ec..2475a54fad 100644 --- a/pkg/kube/exec_test.go +++ b/pkg/kube/exec_test.go @@ -20,10 +20,10 @@ package kube import ( "bytes" "context" - "errors" "strings" "time" + "github.com/kanisterio/errkit" "gopkg.in/check.v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -191,7 +191,7 @@ func (s *ExecSuite) TestErrorInExecWithOptions(c *check.C) { c.Assert(err1, check.Not(check.IsNil)) var ee1 *ExecError - ok := errors.As(err1, &ee1) + ok := errkit.As(err1, &ee1) c.Assert(ok, check.Equals, true) c.Assert(ee1.Stdout(), check.Not(check.Equals), testCase.expectedOut) c.Assert(ee1.Stderr(), check.Not(check.Equals), testCase.expectedErr) @@ -208,7 +208,7 @@ func (s *ExecSuite) TestErrorInExecWithOptions(c *check.C) { c.Assert(err2, check.Not(check.IsNil)) var ee2 *ExecError - ok = errors.As(err2, &ee2) + ok = errkit.As(err2, &ee2) c.Assert(ok, check.Equals, true) // When error happens, stdout/stderr buffers should contain all lines produced by an app diff --git a/pkg/kube/log_reader_test.go b/pkg/kube/log_reader_test.go index b83a89ea29..55fed677c7 100644 --- a/pkg/kube/log_reader_test.go +++ b/pkg/kube/log_reader_test.go @@ -3,9 +3,9 @@ package kube import ( "bytes" "context" - "errors" "io" + "github.com/kanisterio/errkit" "gopkg.in/check.v1" "k8s.io/client-go/rest" ) @@ -39,7 +39,7 @@ func (frw *fakeResponseWrapper) Stream(context.Context) (io.ReadCloser, error) { } func (s *LogReaderSuite) TestLogReader(c *check.C) { - err := errors.New("TEST") + err := errkit.New("TEST") for _, tc := range []struct { rw *fakeResponseWrapper err error diff --git a/pkg/kube/pod.go b/pkg/kube/pod.go index 8baf644565..09be10c94c 100644 --- a/pkg/kube/pod.go +++ b/pkg/kube/pod.go @@ -27,7 +27,6 @@ import ( "github.com/gofrs/uuid" json "github.com/json-iterator/go" "github.com/kanisterio/errkit" - "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -451,7 +450,7 @@ func checkPVCAndPVStatus(ctx context.Context, vol corev1.Volume, p *corev1.Pod, pvcName := vol.VolumeSource.PersistentVolumeClaim.ClaimName pvc, err := cli.CoreV1().PersistentVolumeClaims(namespace).Get(ctx, pvcName, metav1.GetOptions{}) if err != nil { - if apierrors.IsNotFound(errors.Cause(err)) { + if apierrors.IsNotFound(err) { // Do not return err, wait for timeout, since sometimes in case of statefulsets, they trigger creation of a volume return nil } @@ -470,7 +469,7 @@ func checkPVCAndPVStatus(ctx context.Context, vol corev1.Volume, p *corev1.Pod, } pv, err := cli.CoreV1().PersistentVolumes().Get(ctx, pvName, metav1.GetOptions{}) if err != nil { - if apierrors.IsNotFound(errors.Cause(err)) { + if apierrors.IsNotFound(err) { // wait for timeout return nil } diff --git a/pkg/kube/pod_command_executor_test.go b/pkg/kube/pod_command_executor_test.go index bc037dad47..064e6b35c0 100644 --- a/pkg/kube/pod_command_executor_test.go +++ b/pkg/kube/pod_command_executor_test.go @@ -17,11 +17,11 @@ package kube import ( "bytes" "context" - "errors" "os" "sync" "time" + "github.com/kanisterio/errkit" "gopkg.in/check.v1" "k8s.io/client-go/kubernetes/fake" ) @@ -129,7 +129,7 @@ func (s *PodCommandExecutorTestSuite) TestPodRunnerExec(c *check.C) { prp.execWithOptionsSyncEnd.Sync() c.Assert(err, check.Not(check.IsNil)) - c.Assert(errors.Is(err, context.DeadlineExceeded), check.Equals, true) + c.Assert(errkit.Is(err, context.DeadlineExceeded), check.Equals, true) }, "Cancelled": func(ctx context.Context, pr PodCommandExecutor, prp *fakePodCommandExecutorProcessor) { var err error @@ -151,7 +151,7 @@ func (s *PodCommandExecutorTestSuite) TestPodRunnerExec(c *check.C) { prp.execWithOptionsSyncEnd.Sync() // Release ExecWithOptions c.Assert(err, check.Not(check.IsNil)) - c.Assert(errors.Is(err, context.Canceled), check.Equals, true) + c.Assert(errkit.Is(err, context.Canceled), check.Equals, true) }, "Successful execution": func(ctx context.Context, pr PodCommandExecutor, prp *fakePodCommandExecutorProcessor) { var err error diff --git a/pkg/kube/pod_controller_test.go b/pkg/kube/pod_controller_test.go index b2172ca21c..1555070569 100644 --- a/pkg/kube/pod_controller_test.go +++ b/pkg/kube/pod_controller_test.go @@ -16,7 +16,6 @@ package kube import ( "context" - "errors" "fmt" "os" "time" @@ -46,14 +45,14 @@ func (s *PodControllerTestSuite) TestPodControllerStartPod(c *check.C) { ctx := context.Background() cli := fake.NewSimpleClientset() - simulatedError := errors.New("SimulatedError") + simulatedError := errkit.New("SimulatedError") cases := map[string]func(prp *FakePodControllerProcessor, pr PodController){ "Pod creation failure": func(pcp *FakePodControllerProcessor, pc PodController) { pcp.CreatePodErr = simulatedError err := pc.StartPod(ctx) c.Assert(err, check.Not(check.IsNil)) - c.Assert(errors.Is(err, simulatedError), check.Equals, true) + c.Assert(errkit.Is(err, simulatedError), check.Equals, true) c.Assert(pcp.InCreatePodOptions, check.DeepEquals, &PodOptions{ Namespace: podControllerNS, Name: podControllerPodName, @@ -81,11 +80,11 @@ func (s *PodControllerTestSuite) TestPodControllerStartPod(c *check.C) { prp.InCreatePodOptions = nil prp.CreatePodRet = nil - prp.CreatePodErr = errors.New("CreatePod should not be invoked") + prp.CreatePodErr = errkit.New("CreatePod should not be invoked") err = pr.StartPod(ctx) c.Assert(err, check.Not(check.IsNil)) - c.Assert(errors.Is(err, ErrPodControllerPodAlreadyStarted), check.Equals, true) + c.Assert(errkit.Is(err, ErrPodControllerPodAlreadyStarted), check.Equals, true) c.Assert(prp.InCreatePodOptions, check.IsNil) }, } @@ -108,13 +107,13 @@ func (s *PodControllerTestSuite) TestPodControllerWaitPod(c *check.C) { ctx := context.Background() cli := fake.NewSimpleClientset() - simulatedError := errkit.Wrap(errors.New("SimulatedError"), "Wrapped") + simulatedError := errkit.Wrap(errkit.New("SimulatedError"), "Wrapped") cases := map[string]func(pcp *FakePodControllerProcessor, pc PodController){ "Waiting failed because pod not started yet": func(pcp *FakePodControllerProcessor, pc PodController) { err := pc.WaitForPodReady(ctx) c.Assert(err, check.Not(check.IsNil)) - c.Assert(errors.Is(err, ErrPodControllerPodNotStarted), check.Equals, true) + c.Assert(errkit.Is(err, ErrPodControllerPodNotStarted), check.Equals, true) c.Assert(pcp.InCreatePodOptions, check.IsNil) }, "Waiting failed due to timeout": func(pcp *FakePodControllerProcessor, pc PodController) { @@ -132,7 +131,7 @@ func (s *PodControllerTestSuite) TestPodControllerWaitPod(c *check.C) { c.Assert(err, check.Not(check.IsNil)) c.Assert(pcp.InWaitForPodReadyPodName, check.Equals, podControllerPodName) c.Assert(pcp.InWaitForPodReadyNamespace, check.Equals, podControllerNS) - c.Assert(errors.Is(err, pcp.WaitForPodReadyErr), check.Equals, true) + c.Assert(errkit.Is(err, pcp.WaitForPodReadyErr), check.Equals, true) c.Assert(err.Error(), check.Equals, fmt.Sprintf("Pod failed to become ready in time: %s", simulatedError.Error())) // Check that POD deletion was also invoked with expected arguments @@ -169,13 +168,13 @@ func (s *PodControllerTestSuite) TestPodControllerStopPod(c *check.C) { cli := fake.NewSimpleClientset() untouchedStr := "DEADBEEF" - simulatedError := errors.New("SimulatedError") + simulatedError := errkit.New("SimulatedError") cases := map[string]func(pcp *FakePodControllerProcessor, pc PodController){ "Pod not started yet": func(pcp *FakePodControllerProcessor, pc PodController) { err := pc.StopPod(ctx, 30*time.Second, int64(0)) c.Assert(err, check.Not(check.IsNil)) - c.Assert(errors.Is(err, ErrPodControllerPodNotStarted), check.Equals, true) + c.Assert(errkit.Is(err, ErrPodControllerPodNotStarted), check.Equals, true) c.Assert(pcp.InDeletePodPodName, check.Equals, untouchedStr) c.Assert(pcp.InDeletePodNamespace, check.Equals, untouchedStr) }, @@ -192,7 +191,7 @@ func (s *PodControllerTestSuite) TestPodControllerStopPod(c *check.C) { pcp.DeletePodErr = simulatedError err = pc.StopPod(ctx, 30*time.Second, int64(0)) c.Assert(err, check.Not(check.IsNil)) - c.Assert(errors.Is(err, simulatedError), check.Equals, true) + c.Assert(errkit.Is(err, simulatedError), check.Equals, true) }, "Pod successfully deleted": func(pcp *FakePodControllerProcessor, pc PodController) { pcp.CreatePodRet = &corev1.Pod{ @@ -239,12 +238,12 @@ func (s *PodControllerTestSuite) TestPodControllerGetCommandExecutorAndFileWrite pce, err := pc.GetCommandExecutor() c.Assert(pce, check.IsNil) c.Assert(err, check.Not(check.IsNil)) - c.Assert(errors.Is(err, ErrPodControllerPodNotStarted), check.Equals, true) + c.Assert(errkit.Is(err, ErrPodControllerPodNotStarted), check.Equals, true) pfw, err := pc.GetFileWriter() c.Assert(pfw, check.IsNil) c.Assert(err, check.Not(check.IsNil)) - c.Assert(errors.Is(err, ErrPodControllerPodNotStarted), check.Equals, true) + c.Assert(errkit.Is(err, ErrPodControllerPodNotStarted), check.Equals, true) }, "Pod not ready yet": func(pcp *FakePodControllerProcessor, pc PodController) { pcp.CreatePodRet = &corev1.Pod{ @@ -258,12 +257,12 @@ func (s *PodControllerTestSuite) TestPodControllerGetCommandExecutorAndFileWrite pce, err := pc.GetCommandExecutor() c.Assert(pce, check.IsNil) c.Assert(err, check.Not(check.IsNil)) - c.Assert(errors.Is(err, ErrPodControllerPodNotReady), check.Equals, true) + c.Assert(errkit.Is(err, ErrPodControllerPodNotReady), check.Equals, true) pfw, err := pc.GetFileWriter() c.Assert(pfw, check.IsNil) c.Assert(err, check.Not(check.IsNil)) - c.Assert(errors.Is(err, ErrPodControllerPodNotReady), check.Equals, true) + c.Assert(errkit.Is(err, ErrPodControllerPodNotReady), check.Equals, true) }, "CommandExecutor successfully returned": func(pcp *FakePodControllerProcessor, pc PodController) { pcp.CreatePodRet = &corev1.Pod{ diff --git a/pkg/kube/pod_file_writer_test.go b/pkg/kube/pod_file_writer_test.go index c9c45636b1..85e6a95e4b 100644 --- a/pkg/kube/pod_file_writer_test.go +++ b/pkg/kube/pod_file_writer_test.go @@ -17,7 +17,6 @@ package kube import ( "bytes" "context" - "errors" "io" "os" @@ -90,7 +89,7 @@ func (s *PodFileWriterTestSuite) TestPodRunnerWriteFile(c *check.C) { buf := bytes.NewBuffer([]byte("some file content")) remover, err := pfw.Write(ctx, "/path/to/file", buf) c.Assert(err, check.Not(check.IsNil)) - c.Assert(errors.Is(err, simulatedError), check.Equals, true) + c.Assert(errkit.Is(err, simulatedError), check.Equals, true) c.Assert(remover, check.IsNil) c.Assert(pfwp.podWriter.inWriteNamespace, check.Equals, podFileWriterNS) @@ -130,7 +129,7 @@ func (s *PodFileWriterTestSuite) TestPodRunnerWriteFile(c *check.C) { err = remover.Remove(ctx) c.Assert(err, check.Not(check.IsNil)) - c.Assert(errors.Is(err, simulatedError), check.Equals, true) + c.Assert(errkit.Is(err, simulatedError), check.Equals, true) c.Assert(pfwp.podWriter.inRemoveNamespace, check.Equals, podFileWriterNS) c.Assert(pfwp.podWriter.inRemovePodName, check.Equals, podFileWriterPodName) c.Assert(pfwp.podWriter.inRemoveContainerName, check.Equals, podFileWriterContainerName) diff --git a/pkg/kube/pod_runner_test.go b/pkg/kube/pod_runner_test.go index a3b8c21d61..20a312b1c8 100644 --- a/pkg/kube/pod_runner_test.go +++ b/pkg/kube/pod_runner_test.go @@ -19,7 +19,7 @@ import ( "os" "path" - "github.com/pkg/errors" + "github.com/kanisterio/errkit" "gopkg.in/check.v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" @@ -191,10 +191,10 @@ func afterPodRunTestKeyPresentFunc(labelKey, expectedLabelValue string, isLabelE <-ch labelValue, found := pc.Pod().Labels[labelKey] if found != isLabelExpected { - return nil, errors.New("Got different label than expected") + return nil, errkit.New("Got different label than expected") } if isLabelExpected && labelValue != expectedLabelValue { - return nil, errors.New("Found label doesn't match with expected label") + return nil, errkit.New("Found label doesn't match with expected label") } return nil, nil } diff --git a/pkg/kube/pod_test.go b/pkg/kube/pod_test.go index 852dd29f10..e14878821b 100644 --- a/pkg/kube/pod_test.go +++ b/pkg/kube/pod_test.go @@ -19,14 +19,15 @@ package kube import ( "context" - "errors" "fmt" "os" "strings" "time" + "github.com/kanisterio/errkit" "gopkg.in/check.v1" corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -315,7 +316,7 @@ func (s *PodSuite) TestPodWithFilesystemModeVolumes(c *check.C) { ca := action.(testing.CreateAction) p = ca.GetObject().(*corev1.Pod) if len(p.Spec.Volumes[0].Name) > 63 { - return true, nil, errors.New("spec.volumes[0].name must be no more than 63 characters") + return true, nil, errkit.New("spec.volumes[0].name must be no more than 63 characters") } return false, nil, nil }) @@ -364,7 +365,7 @@ func (s *PodSuite) TestPodWithFilesystemModeReadOnlyVolumes(c *check.C) { ca := action.(testing.CreateAction) p = ca.GetObject().(*corev1.Pod) if len(p.Spec.Volumes[0].Name) > 63 { - return true, nil, errors.New("spec.volumes[0].name must be no more than 63 characters") + return true, nil, errkit.New("spec.volumes[0].name must be no more than 63 characters") } return false, nil, nil }) @@ -415,7 +416,7 @@ func (s *PodSuite) TestPodWithBlockModeVolumes(c *check.C) { ca := action.(testing.CreateAction) p = ca.GetObject().(*corev1.Pod) if len(p.Spec.Volumes[0].Name) > 63 { - return true, nil, errors.New("spec.volumes[0].name must be no more than 63 characters") + return true, nil, errkit.New("spec.volumes[0].name must be no more than 63 characters") } return false, nil, nil }) @@ -1244,3 +1245,19 @@ func (s *PodSuite) TestAddAnnotations(c *check.C) { c.Assert(tc.podOptions, check.DeepEquals, tc.expectedPodOptions) } } + +// TestErrkitApiErrorsWrapping verifies that apierrors wrapped with errkit.Wrap are still matchable using apierrors matchers +func (s *PodSuite) TestErrkitApiErrorsWrapping(c *check.C) { + // Create the fake client + fakeClient := fake.NewSimpleClientset() + + // Add a reactor to simulate an error when trying to get a PVC + fakeClient.PrependReactor("get", "persistentvolumeclaims", func(action testing.Action) (handled bool, ret runtime.Object, err error) { + return true, nil, errkit.Wrap(apierrors.NewNotFound(action.GetResource().GroupResource(), action.GetSubresource()), "Some context") + }) + + _, err := fakeClient.CoreV1().PersistentVolumeClaims("abc").Get(context.TODO(), "def", metav1.GetOptions{}) + if err != nil { + c.Assert(apierrors.IsNotFound(err), check.Equals, true) + } +} diff --git a/pkg/log/fluentbit.go b/pkg/log/fluentbit.go index 36a03397a3..2c2d11cf22 100644 --- a/pkg/log/fluentbit.go +++ b/pkg/log/fluentbit.go @@ -7,7 +7,7 @@ import ( "os" "time" - "github.com/pkg/errors" + "github.com/kanisterio/errkit" "github.com/sirupsen/logrus" ) @@ -64,7 +64,7 @@ func NewFluentbitHook(endpoint string) *FluentbitHook { func dial(endpoint string) (net.Conn, error) { conn, err := net.DialTimeout("tcp", endpoint, defaultConnTimeout) if err != nil { - return nil, errors.Wrap(err, "Fluentbit connection problem") + return nil, errkit.Wrap(err, "Fluentbit connection problem") } return conn, nil } @@ -73,12 +73,12 @@ func dial(endpoint string) (net.Conn, error) { func handle(msgs []byte, endpoint string) error { conn, err := dial(endpoint) if err != nil { - return errors.Wrap(err, "Fluentbit connection error") + return errkit.Wrap(err, "Fluentbit connection error") } defer conn.Close() //nolint:errcheck _, err = conn.Write(msgs) if err != nil { - return errors.Wrap(err, "Fluentbit write error") + return errkit.Wrap(err, "Fluentbit write error") } return nil } diff --git a/pkg/log/log.go b/pkg/log/log.go index fcd1932cb0..a5363fbc16 100644 --- a/pkg/log/log.go +++ b/pkg/log/log.go @@ -9,7 +9,7 @@ import ( "strings" "time" - "github.com/pkg/errors" + "github.com/kanisterio/errkit" "github.com/sirupsen/logrus" "github.com/kanisterio/kanister/pkg/caller" @@ -34,9 +34,9 @@ const ( ) var ( - ErrEndpointNotSet = errors.New("fluentbit endpoint not set") - ErrNonTCPEndpoint = errors.New("fluentbit endpoint scheme must be tcp") - ErrPathSet = errors.New("fluentbit endpoint path is set") + ErrEndpointNotSet = errkit.NewSentinelErr("fluentbit endpoint not set") + ErrNonTCPEndpoint = errkit.NewSentinelErr("fluentbit endpoint scheme must be tcp") + ErrPathSet = errkit.NewSentinelErr("fluentbit endpoint path is set") ) // OutputSink describes the current output sink. @@ -72,17 +72,17 @@ func SetOutput(sink OutputSink) error { case FluentbitSink: fbitAddr, ok := os.LookupEnv(LoggingServiceHostEnv) if !ok { - return errors.New("Unable to find Fluentbit host address") + return errkit.New("Unable to find Fluentbit host address") } fbitPort, ok := os.LookupEnv(LoggingServicePortEnv) if !ok { - return errors.New("Unable to find Fluentbit logging port") + return errkit.New("Unable to find Fluentbit logging port") } hook := NewFluentbitHook(fbitAddr + ":" + fbitPort) log.AddHook(hook) return nil default: - return errors.New("not implemented") + return errkit.New("not implemented") } } diff --git a/pkg/log/log_test.go b/pkg/log/log_test.go index 838942d7eb..2cb20b1e76 100644 --- a/pkg/log/log_test.go +++ b/pkg/log/log_test.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "errors" "fmt" "net/url" "os" @@ -12,6 +11,7 @@ import ( "testing" "time" + "github.com/kanisterio/errkit" "github.com/sirupsen/logrus" "gopkg.in/check.v1" @@ -59,7 +59,7 @@ func (s *LogSuite) TestLogWithFields(c *check.C) { func (s *LogSuite) TestLogWithError(c *check.C) { const text = "My error message" - err := errors.New("test error") + err := errkit.New("test error") entry := testLogMessage(c, text, WithError(err).Print) c.Assert(entry["error"], check.Equals, err.Error()) c.Assert(entry["level"], check.Equals, infoLevelStr) @@ -88,7 +88,7 @@ func (s *LogSuite) TestLogWithContextFields(c *check.C) { func (s *LogSuite) TestLogWithContextFieldsAndError(c *check.C) { const text = "My error message" ctx := field.Context(context.Background(), "key", "value") - err := errors.New("test error") + err := errkit.New("test error") entry := testLogMessage(c, text, WithError(err).WithContext(ctx).Print) c.Assert(entry["level"], check.Equals, infoLevelStr) // Error should be included in the log entry diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go index 7831683a47..011d1debf3 100644 --- a/pkg/metrics/metrics.go +++ b/pkg/metrics/metrics.go @@ -15,9 +15,9 @@ package metrics import ( - "errors" "fmt" + "github.com/kanisterio/errkit" "github.com/prometheus/client_golang/prometheus" "gonum.org/v1/gonum/stat/combin" @@ -73,7 +73,7 @@ func getLabelCombinations(bl []BoundedLabel) ([]prometheus.Labels, error) { {"operation_type": "restore", "action_set_resolution": "failure"}] */ if !verifyBoundedLabels(bl) { - return nil, errors.New("invalid BoundedLabel list") + return nil, errkit.New("invalid BoundedLabel list") } labelLens := make([]int, len(bl)) for idx, l := range bl { @@ -241,7 +241,7 @@ func registerGauge(r prometheus.Registerer, g prometheus.Gauge) prometheus.Gauge func registerMetricOrDie(r prometheus.Registerer, c prometheus.Collector) prometheus.Collector { if err := r.Register(c); err != nil { are := prometheus.AlreadyRegisteredError{} - if !errors.As(err, &are) { + if !errkit.As(err, &are) { panic(fmt.Sprintf("failed to register metric. error: %v", err)) } // Use already registered metric diff --git a/pkg/objectstore/directory.go b/pkg/objectstore/directory.go index f184c29449..d228230cc1 100644 --- a/pkg/objectstore/directory.go +++ b/pkg/objectstore/directory.go @@ -234,7 +234,7 @@ func (d *directory) Put(ctx context.Context, name string, r io.Reader, size int6 if d.path == "" { return errors.New("invalid entry") } - // K10 tags include '/'. Remove them, at least for S3 + // Replace any '/' in tags with '-'. sTags := sanitizeTags(tags) objName := d.absPathName(name) diff --git a/pkg/testing/e2e_test.go b/pkg/testing/e2e_test.go index 17ef519cd3..3e3ffd41e0 100644 --- a/pkg/testing/e2e_test.go +++ b/pkg/testing/e2e_test.go @@ -23,7 +23,7 @@ import ( "log" "time" - "github.com/pkg/errors" + "github.com/kanisterio/errkit" "gopkg.in/check.v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -166,7 +166,7 @@ func (s *E2ESuite) TestKubeExec(c *check.C) { case err != nil, as.Status == nil: return false, err case as.Status.State == crv1alpha1.StateFailed: - return true, errors.Errorf("Actionset failed: %#v", as.Status) + return true, errkit.New(fmt.Sprintf("Actionset failed: %#v", as.Status)) case as.Status.State == crv1alpha1.StateComplete: return true, nil } @@ -290,7 +290,7 @@ func (s *E2ESuite) TestKubeTask(c *check.C) { case err != nil, as.Status == nil: return false, err case as.Status.State == crv1alpha1.StateFailed: - return true, errors.Errorf("Actionset failed: %#v", as.Status) + return true, errkit.New(fmt.Sprintf("Actionset failed: %#v", as.Status)) case as.Status.State == crv1alpha1.StateComplete: return true, nil } @@ -524,7 +524,7 @@ func (s *E2ESuite) waitForActionSetComplete(asName string) error { case err != nil, as.Status == nil: return false, err case as.Status.State == crv1alpha1.StateFailed: - return true, errors.Errorf("Actionset failed: %#v", as.Status) + return true, errkit.New(fmt.Sprintf("Actionset failed: %#v", as.Status)) case as.Status.State == crv1alpha1.StateComplete: return true, nil } @@ -553,7 +553,7 @@ func (s *E2ESuite) waitForFunctionPodReady() error { } if len(pods.Items) > 1 { - return false, errors.New("more than one kanister-job pod found") + return false, errkit.New("more than one kanister-job pod found") } return true, nil @@ -564,7 +564,7 @@ func verifyAnnotationsInFunctionPod(funcPodAnnotations, expectedAnnotations map[ for k, v := range expectedAnnotations { val, ok := funcPodAnnotations[k] if !ok || v != val { - return errors.New(fmt.Sprintf("Either key %s, is not found in pod annotations or, its values (%s and %s) don't match", k, v, val)) + return errkit.New(fmt.Sprintf("Either key %s, is not found in pod annotations or, its values (%s and %s) don't match", k, v, val)) } } return nil @@ -574,7 +574,7 @@ func verifyLabelsInFunctionPod(funcPodLabels, expectedLabels map[string]string) for k, v := range expectedLabels { val, ok := funcPodLabels[k] if !ok || v != val { - return errors.New(fmt.Sprintf("Either key %s, is not found in pod labels or, its values (%s and %s) don't match", k, v, val)) + return errkit.New(fmt.Sprintf("Either key %s, is not found in pod labels or, its values (%s and %s) don't match", k, v, val)) } } return nil diff --git a/pkg/testing/integration_test.go b/pkg/testing/integration_test.go index 80bce4d248..baf3ca8fc7 100644 --- a/pkg/testing/integration_test.go +++ b/pkg/testing/integration_test.go @@ -18,12 +18,13 @@ package testing import ( - context "context" + "context" + "fmt" "os" test "testing" "time" - "github.com/pkg/errors" + "github.com/kanisterio/errkit" "gopkg.in/check.v1" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" @@ -425,7 +426,7 @@ func (s *IntegrationSuite) createActionset(ctx context.Context, c *check.C, as * case err != nil, as.Status == nil: return false, err case as.Status.State == crv1alpha1.StateFailed: - return true, errors.Errorf("Actionset failed: %#v", as.Status) + return true, errkit.New(fmt.Sprintf("Actionset failed: %#v", as.Status)) case as.Status.State == crv1alpha1.StateComplete: return true, nil } diff --git a/pkg/testutil/func.go b/pkg/testutil/func.go index 8e5beabdf6..bb45370478 100644 --- a/pkg/testutil/func.go +++ b/pkg/testutil/func.go @@ -18,7 +18,7 @@ import ( "context" "time" - "github.com/pkg/errors" + "github.com/kanisterio/errkit" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kanister "github.com/kanisterio/kanister/pkg" @@ -48,7 +48,7 @@ var ( ) func failFunc(context.Context, param.TemplateParams, map[string]interface{}) (map[string]interface{}, error) { - err := errors.New("Kanister function failed") + err := errkit.New("Kanister function failed") failFuncCh <- err return nil, err } diff --git a/pkg/testutil/mockblockstorage/mockblockstorage.go b/pkg/testutil/mockblockstorage/mockblockstorage.go index d36e38e565..9275cf4a60 100644 --- a/pkg/testutil/mockblockstorage/mockblockstorage.go +++ b/pkg/testutil/mockblockstorage/mockblockstorage.go @@ -20,7 +20,7 @@ import ( "time" uuid "github.com/gofrs/uuid" - "github.com/pkg/errors" + "github.com/kanisterio/errkit" "github.com/kanisterio/kanister/pkg/blockstorage" "github.com/kanisterio/kanister/pkg/blockstorage/getter" @@ -57,7 +57,7 @@ func (*mockGetter) Get(storageType blockstorage.Type, config map[string]string) case blockstorage.TypeGPD: return Get(storageType) default: - return nil, errors.New("Get failed") + return nil, errkit.New("Get failed") } } @@ -65,7 +65,7 @@ func (*mockGetter) Get(storageType blockstorage.Type, config map[string]string) func Get(storageType blockstorage.Type) (*Provider, error) { volumeUUID, err := uuid.NewV1() if err != nil { - return nil, errors.Wrap(err, "Failed to create UUID") + return nil, errkit.Wrap(err, "Failed to create UUID") } volume := blockstorage.Volume{ Type: storageType, @@ -84,7 +84,7 @@ func Get(storageType blockstorage.Type) (*Provider, error) { snapVol := volume snapUUID, err := uuid.NewV1() if err != nil { - return nil, errors.Wrap(err, "Failed to create UUID") + return nil, errkit.Wrap(err, "Failed to create UUID") } snapshot := blockstorage.Snapshot{ Type: storageType, @@ -122,7 +122,7 @@ func (p *Provider) VolumeCreate(context.Context, blockstorage.Volume) (*blocksto func (p *Provider) VolumeCreateFromSnapshot(ctx context.Context, snapshot blockstorage.Snapshot, tags map[string]string) (*blockstorage.Volume, error) { volUUID, err := uuid.NewV1() if err != nil { - return nil, errors.Wrap(err, "Failed to create UUID") + return nil, errkit.Wrap(err, "Failed to create UUID") } vol := blockstorage.Volume{ Type: snapshot.Type, @@ -197,7 +197,7 @@ func (p *Provider) SetTags(ctx context.Context, resource interface{}, tags map[s case *blockstorage.Snapshot: return nil default: - return errors.Errorf("Unsupported resource type %v(%T)", res, res) + return errkit.New(fmt.Sprintf("Unsupported resource type %v(%T)", res, res)) } } diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 55aff0c8dc..396472f324 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -23,7 +23,7 @@ import ( "strings" "time" - "github.com/pkg/errors" + "github.com/kanisterio/errkit" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -56,7 +56,7 @@ func PrintStage(description string, i indicator) { func GetNamespaceUID(ctx context.Context, cli kubernetes.Interface, namespace string) (string, error) { ns, err := cli.CoreV1().Namespaces().Get(ctx, namespace, metav1.GetOptions{}) if err != nil { - return "", errors.Wrapf(err, "Failed to get namespace %s", namespace) + return "", errkit.Wrap(err, "Failed to get namespace", "namespace", namespace) } return string(ns.GetUID()), nil } @@ -85,7 +85,7 @@ func GetIntOrDefault(value string, defaultValue int) (int, error) { v, err := strconv.Atoi(value) if err != nil { v = defaultValue - return v, errors.New("conversion to integer failed, using default value for the field") + return v, errkit.New("conversion to integer failed, using default value for the field") } return v, nil } @@ -121,7 +121,7 @@ func RoundUpDuration(t time.Duration) time.Duration { func CheckRequiredArgs(reqArgs []string, args map[string]interface{}) error { for _, a := range reqArgs { if _, ok := args[a]; !ok { - return errors.Errorf("Required arg missing: %s", a) + return errkit.New(fmt.Sprintf("Required arg missing: %s", a)) } } return nil @@ -132,7 +132,7 @@ func CheckRequiredArgs(reqArgs []string, args map[string]interface{}) error { func CheckSupportedArgs(supportedArgs []string, args map[string]interface{}) error { for a := range args { if !slices.Contains(supportedArgs, a) { - return errors.Errorf("argument %s is not supported", a) + return errkit.New(fmt.Sprintf("argument %s is not supported", a)) } } return nil diff --git a/pkg/validate/error.go b/pkg/validate/error.go index 5011e94a25..50c4c591a4 100644 --- a/pkg/validate/error.go +++ b/pkg/validate/error.go @@ -15,18 +15,16 @@ package validate import ( - "fmt" - - "github.com/pkg/errors" + "github.com/kanisterio/errkit" ) -var errValidate = fmt.Errorf("Validation Failed") +var errValidate = errkit.NewSentinelErr("Validation Failed") func errorf(err error, format string, args ...interface{}) error { - return errors.Wrapf(err, format, args...) + return errkit.Wrap(err, format, args...) } -// IsError returns true iff the underlying cause was a validation error. +// IsError returns true if the underlying cause was a validation error. func IsError(err error) bool { - return errors.Cause(err) == errValidate + return errkit.Is(err, errValidate) } diff --git a/pkg/validate/error_test.go b/pkg/validate/error_test.go index 05b9cba995..cf86806870 100644 --- a/pkg/validate/error_test.go +++ b/pkg/validate/error_test.go @@ -17,7 +17,7 @@ package validate import ( "fmt" - "github.com/pkg/errors" + "github.com/kanisterio/errkit" "gopkg.in/check.v1" ) @@ -43,23 +43,23 @@ func (s *ErrorSuite) TestIsError(c *check.C) { is: true, }, { - err: errors.Wrap(nil, "test"), + err: errkit.Wrap(nil, "test"), is: false, }, { - err: errors.WithStack(nil), + err: errkit.WithStack(nil), is: false, }, { - err: errors.Wrap(errValidate, "test"), + err: errkit.Wrap(errValidate, "test"), is: true, }, { - err: errors.WithStack(errValidate), + err: errkit.WithStack(errValidate), is: true, }, { - err: errors.New("test"), + err: errkit.New("test"), is: false, }, } { diff --git a/pkg/validatingwebhook/repositoryserver_handler.go b/pkg/validatingwebhook/repositoryserver_handler.go index b3b9c3509e..b401050c99 100644 --- a/pkg/validatingwebhook/repositoryserver_handler.go +++ b/pkg/validatingwebhook/repositoryserver_handler.go @@ -18,7 +18,7 @@ import ( "context" "fmt" - "github.com/pkg/errors" + "github.com/kanisterio/errkit" "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" @@ -43,11 +43,11 @@ func (r *RepositoryServerValidator) ValidateUpdate(ctx context.Context, old runt oldrs, ook := old.(*crv1alpha1.RepositoryServer) newrs, nok := new.(*crv1alpha1.RepositoryServer) if !ook || !nok { - return nil, errors.New("Either updated object or the old object is not of type RepositoryServer.cr.kanister.io") + return nil, errkit.New("Either updated object or the old object is not of type RepositoryServer.cr.kanister.io") } errMsg := fmt.Sprintf("RepositoryServer.cr.kanister.io \"%s\" is invalid: spec.repository.rootPath: Invalid value, Value is immutable", newrs.Name) if oldrs.Spec.Repository.RootPath != newrs.Spec.Repository.RootPath { - return nil, errors.New(errMsg) + return nil, errkit.New(errMsg) } return nil, nil }