From 68f3fffe6208fc7392a1e5c9e362cacaf85e3945 Mon Sep 17 00:00:00 2001 From: Carlos Tadeu Panato Junior Date: Fri, 16 Sep 2022 15:59:15 +0200 Subject: [PATCH] Upgrade go1.19, helm update and add golangci-lint job (#460) * upgrade to go1.19 Signed-off-by: cpanato * add golangci-lint Signed-off-by: cpanato * fix lints and Replace github.com/pkg/errors dependency with native error wrapping Signed-off-by: cpanato * update install kind cluster Signed-off-by: cpanato * update tests Signed-off-by: cpanato * use errors.new Signed-off-by: cpanato Signed-off-by: cpanato --- .github/workflows/ci.yaml | 31 ++++++-- .github/workflows/release.yaml | 8 +- .golangci.yml | 31 ++++++++ Dockerfile | 2 +- ct/cmd/install.go | 4 +- ct/cmd/lint.go | 4 +- ct/cmd/lintAndInstall.go | 4 +- ct/cmd/listChanged.go | 3 +- e2e-kind.sh | 2 +- go.mod | 3 +- go.sum | 1 - pkg/chart/chart.go | 141 ++++++++++++++++----------------- pkg/chart/chart_test.go | 8 +- pkg/chart/integration_test.go | 4 +- pkg/config/config.go | 14 ++-- pkg/config/config_test.go | 2 +- pkg/exec/exec.go | 25 +++--- pkg/tool/account.go | 10 +-- pkg/tool/account_test.go | 6 +- pkg/tool/cmdexecutor_test.go | 2 +- pkg/tool/git.go | 5 +- pkg/tool/helm.go | 2 +- pkg/tool/kubectl.go | 22 ++--- pkg/util/util.go | 47 ++++++----- 24 files changed, 211 insertions(+), 170 deletions(-) create mode 100644 .golangci.yml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c2c83b7c..406ba7df 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -12,7 +12,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.1 + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3 with: fetch-depth: 0 @@ -22,7 +22,7 @@ jobs: - name: Setup go uses: actions/setup-go@268d8c0ca0432bb2cf416faae41297df9d262d7f # v3.3.0 with: - go-version: '1.18' + go-version-file: './go.mod' check-latest: true - uses: azure/setup-helm@b5b231a831f96336bbfeccc1329990f0005c5bb1 # v3.3 @@ -40,16 +40,17 @@ jobs: - name: Install syft uses: anchore/sbom-action/download-syft@b5042e9d19d8b32849779bfe17673ff84aec702d # v0.12.0 + - name: Install k8s Kind + uses: helm/kind-action@d08cf6ff1575077dee99962540d77ce91c62387d # v1.3.0 + with: + install_only: true + - name: Install tools run: | curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl chmod +x ./kubectl sudo mv ./kubectl /usr/local/bin/kubectl - curl -fsSLo kind "https://github.com/kubernetes-sigs/kind/releases/download/v0.14.0/kind-linux-amd64" - chmod +x kind - sudo mv kind /usr/local/bin/kind - ./setup.sh - name: Test @@ -64,10 +65,10 @@ jobs: git diff --exit-code - name: Set up QEMU - uses: docker/setup-qemu-action@8b122486cedac8393e77aa9734c3528886e4a1a8 # v1.2.0 + uses: docker/setup-qemu-action@8b122486cedac8393e77aa9734c3528886e4a1a8 # v2.0.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@dc7b9719a96d48369863986a06765841d7ea23f6 # v1.6.0 + uses: docker/setup-buildx-action@dc7b9719a96d48369863986a06765841d7ea23f6 # v2.0.0 - name: Build run: | @@ -76,3 +77,17 @@ jobs: echo "Building snapshot..." ./build.sh + + golangci: + name: lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3 + - uses: actions/setup-go@84cbf8094393cdc5fe1fe1671ff2647332956b1a # v3 + with: + go-version-file: './go.mod' + check-latest: true + - name: golangci-lint + uses: golangci/golangci-lint-action@537aa1903e5d359d0b27dbc19ddd22c5087f3fbc # v3 + with: + version: v1.48.0 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index e1c12f65..f2e2e150 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -27,7 +27,7 @@ jobs: - name: Setup go uses: actions/setup-go@268d8c0ca0432bb2cf416faae41297df9d262d7f # v3.3.0 with: - go-version: '1.18' + go-version-file: './go.mod' check-latest: true - name: Install GoReleaser @@ -53,13 +53,13 @@ jobs: git diff --exit-code - name: Set up QEMU - uses: docker/setup-qemu-action@8b122486cedac8393e77aa9734c3528886e4a1a8 # v1.2.0 + uses: docker/setup-qemu-action@8b122486cedac8393e77aa9734c3528886e4a1a8 # v2.0.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@dc7b9719a96d48369863986a06765841d7ea23f6 # v1.6.0 + uses: docker/setup-buildx-action@dc7b9719a96d48369863986a06765841d7ea23f6 # v2.0.0 - name: Login to registry - uses: docker/login-action@49ed152c8eca782a232dede0303416e8f356c37b # v1.14.1 + uses: docker/login-action@49ed152c8eca782a232dede0303416e8f356c37b # v2.0.0 with: registry: quay.io username: ${{ secrets.DOCKER_USERNAME }} diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 00000000..866db008 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,31 @@ +linters: + enable: + - asciicheck + - deadcode + - depguard + - errcheck + - errorlint + - gofmt + - goimports + - gosec + - gocritic + - importas + - prealloc + - revive + - misspell + - stylecheck + - unconvert + - whitespace +output: + uniq-by-line: false +issues: + exclude-rules: + - path: _test\.go + linters: + - errcheck + - gosec + max-issues-per-linter: 0 + max-same-issues: 0 +run: + issues-exit-code: 1 + timeout: 10m diff --git a/Dockerfile b/Dockerfile index 59be87c2..b076f535 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,7 +30,7 @@ RUN curl -LO "https://storage.googleapis.com/kubernetes-release/release/$kubectl mv kubectl /usr/local/bin/ # Install Helm -ARG helm_version=v3.9.2 +ARG helm_version=v3.9.3 LABEL helm_version=$helm_version RUN targetArch=$(echo $TARGETPLATFORM | cut -f2 -d '/') \ && if [ ${targetArch} = "amd64" ]; then \ diff --git a/ct/cmd/install.go b/ct/cmd/install.go index 12e76b55..41b234d2 100644 --- a/ct/cmd/install.go +++ b/ct/cmd/install.go @@ -91,7 +91,7 @@ func install(cmd *cobra.Command, args []string) error { } configuration, err := config.LoadConfiguration(cfgFile, cmd, printConfig) if err != nil { - return fmt.Errorf("Error loading configuration: %s", err) + return fmt.Errorf("failed loading configuration: %w", err) } extraSetArgs, err := cmd.Flags().GetString("helm-extra-set-args") @@ -106,7 +106,7 @@ func install(cmd *cobra.Command, args []string) error { testing.PrintResults(results) if err != nil { - return fmt.Errorf("Error installing charts: %s", err) + return fmt.Errorf("failed installing charts: %w", err) } fmt.Println("All charts installed successfully") diff --git a/ct/cmd/lint.go b/ct/cmd/lint.go index 2656a4ab..dd36f0f7 100644 --- a/ct/cmd/lint.go +++ b/ct/cmd/lint.go @@ -85,7 +85,7 @@ func lint(cmd *cobra.Command, args []string) error { } configuration, err := config.LoadConfiguration(cfgFile, cmd, printConfig) if err != nil { - return fmt.Errorf("Error loading configuration: %s", err) + return fmt.Errorf("failed loading configuration: %w", err) } emptyExtraSetArgs := "" @@ -97,7 +97,7 @@ func lint(cmd *cobra.Command, args []string) error { testing.PrintResults(results) if err != nil { - return fmt.Errorf("Error linting charts: %s", err) + return fmt.Errorf("failed linting charts: %w", err) } fmt.Println("All charts linted successfully") diff --git a/ct/cmd/lintAndInstall.go b/ct/cmd/lintAndInstall.go index 0ec6238c..c42a6494 100644 --- a/ct/cmd/lintAndInstall.go +++ b/ct/cmd/lintAndInstall.go @@ -48,7 +48,7 @@ func lintAndInstall(cmd *cobra.Command, args []string) error { } configuration, err := config.LoadConfiguration(cfgFile, cmd, printConfig) if err != nil { - return fmt.Errorf("Error loading configuration: %s", err) + return fmt.Errorf("failed loading configuration: %w", err) } extraSetArgs, err := cmd.Flags().GetString("helm-extra-set-args") @@ -63,7 +63,7 @@ func lintAndInstall(cmd *cobra.Command, args []string) error { testing.PrintResults(results) if err != nil { - return fmt.Errorf("Error linting and installing charts: %s", err) + return fmt.Errorf("failed linting and installing charts: %w", err) } fmt.Println("All charts linted and installed successfully") diff --git a/ct/cmd/listChanged.go b/ct/cmd/listChanged.go index 4c286e37..412f7c1a 100644 --- a/ct/cmd/listChanged.go +++ b/ct/cmd/listChanged.go @@ -47,7 +47,7 @@ func listChanged(cmd *cobra.Command, args []string) error { } configuration, err := config.LoadConfiguration(cfgFile, cmd, printConfig) if err != nil { - return fmt.Errorf("Error loading configuration: %s", err) + return fmt.Errorf("failed loading configuration: %w", err) } emptyExtraSetArgs := "" @@ -63,5 +63,6 @@ func listChanged(cmd *cobra.Command, args []string) error { for _, dir := range chartDirs { fmt.Println(dir) } + return nil } diff --git a/e2e-kind.sh b/e2e-kind.sh index 796d6561..c8cff13c 100755 --- a/e2e-kind.sh +++ b/e2e-kind.sh @@ -7,7 +7,7 @@ set -o pipefail CLUSTER_NAME=chart-testing readonly CLUSTER_NAME -K8S_VERSION=v1.21.2 +K8S_VERSION=v1.22.9 readonly K8S_VERSION create_kind_cluster() { diff --git a/go.mod b/go.mod index 302a70b1..35d27037 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/helm/chart-testing/v3 -go 1.18 +go 1.19 require ( github.com/MakeNowJust/heredoc v1.0.0 @@ -9,7 +9,6 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.1 github.com/mattn/go-shellwords v1.0.12 github.com/mitchellh/go-homedir v1.1.0 - github.com/pkg/errors v0.9.1 github.com/spf13/cobra v1.5.0 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.13.0 diff --git a/go.sum b/go.sum index 2b2d9802..0f35e49d 100644 --- a/go.sum +++ b/go.sum @@ -168,7 +168,6 @@ github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= diff --git a/pkg/chart/chart.go b/pkg/chart/chart.go index c66c8e0b..2c63f98f 100644 --- a/pkg/chart/chart.go +++ b/pkg/chart/chart.go @@ -15,8 +15,8 @@ package chart import ( + "errors" "fmt" - "io/ioutil" "os" "path/filepath" "strings" @@ -27,7 +27,6 @@ import ( "github.com/helm/chart-testing/v3/pkg/exec" "github.com/helm/chart-testing/v3/pkg/tool" "github.com/helm/chart-testing/v3/pkg/util" - "github.com/pkg/errors" ) const maxNameLength = 63 @@ -46,7 +45,7 @@ const maxNameLength = 63 // // ListChangedFilesInDirs diffs commit against HEAD and returns changed files for the specified dirs. // -// GetUrlForRemote returns the repo URL for the specified remote. +// GetURLForRemote returns the repo URL for the specified remote. // // ValidateRepository checks that the current working directory is a valid git repository, // and returns nil if valid. @@ -57,17 +56,17 @@ type Git interface { RemoveWorktree(path string) error MergeBase(commit1 string, commit2 string) (string, error) ListChangedFilesInDirs(commit string, dirs ...string) ([]string, error) - GetUrlForRemote(remote string) (string, error) + GetURLForRemote(remote string) (string, error) ValidateRepository() error } // Helm is the interface that wraps Helm operations // -// AddRepo adds a chart repository to the local Helm configuration +// # AddRepo adds a chart repository to the local Helm configuration // -// BuildDependencies builds the chart's dependencies +// # BuildDependencies builds the chart's dependencies // -// BuildDependenciesWithArgs allows passing additional arguments to BuildDependencies +// # BuildDependenciesWithArgs allows passing additional arguments to BuildDependencies // // LintWithValues runs `helm lint` for the given chart using the specified values file. // Pass a zero value for valuesFile in order to run lint without specifying a values file. @@ -95,21 +94,21 @@ type Helm interface { // Kubectl is the interface that wraps kubectl operations // -// DeleteNamespace deletes a namespace +// # DeleteNamespace deletes a namespace // -// WaitForDeployments waits for a deployment to become ready +// # WaitForDeployments waits for a deployment to become ready // -// GetPodsforDeployment gets all pods for a deployment +// # GetPodsforDeployment gets all pods for a deployment // -// GetPods gets pods for the given args +// # GetPods gets pods for the given args // -// GetEvents prints all events for namespace +// # GetEvents prints all events for namespace // -// DescribePod prints the pod's description +// # DescribePod prints the pod's description // -// Logs prints the logs of container +// # Logs prints the logs of container // -// GetInitContainers gets all init containers of pod +// # GetInitContainers gets all init containers of pod // // GetContainers gets all containers of pod type Kubectl interface { @@ -127,7 +126,7 @@ type Kubectl interface { // Linter is the interface that wrap linting operations // -// YamlLint runs `yamllint` on the specified file with the specified configuration +// # YamlLint runs `yamllint` on the specified file with the specified configuration // // Yamale runs `yamale` on the specified file with the specified schema file type Linter interface { @@ -149,10 +148,10 @@ type DirectoryLister interface { ListChildDirs(parentDir string, test func(string) bool) ([]string, error) } -// ChartUtils is the interface that wraps chart-related methods +// Utils is the interface that wraps chart-related methods // // LookupChartDir looks up the chart's root directory based on some chart file that has changed -type ChartUtils interface { +type Utils interface { LookupChartDir(chartDirs []string, dir string) (string, error) } @@ -238,7 +237,7 @@ type Testing struct { cmdExecutor CmdExecutor accountValidator AccountValidator directoryLister DirectoryLister - chartUtils ChartUtils + utils Utils previousRevisionWorktree string } @@ -268,7 +267,7 @@ func NewTesting(config config.Configuration, extraSetArgs string) (Testing, erro cmdExecutor: tool.NewCmdTemplateExecutor(procExec), accountValidator: tool.AccountValidator{}, directoryLister: util.DirectoryLister{}, - chartUtils: util.ChartUtils{}, + utils: util.Utils{}, } versionString, err := testing.helm.Version() @@ -294,10 +293,10 @@ func (t *Testing) computePreviousRevisionPath(fileOrDirPath string) string { } func (t *Testing) processCharts(action func(chart *Chart) TestResult) ([]TestResult, error) { - var results []TestResult + var results []TestResult // nolint: prealloc chartDirs, err := t.FindChartDirsToBeProcessed() if err != nil { - return nil, errors.Wrap(err, "Error identifying charts to process") + return nil, fmt.Errorf("failed identifying charts to process: %w", err) } else if len(chartDirs) == 0 { return results, nil } @@ -310,20 +309,20 @@ func (t *Testing) processCharts(action func(chart *Chart) TestResult) ([]TestRes } if t.config.ExcludeDeprecated && chart.yaml.Deprecated { - fmt.Printf("Chart '%s' is deprecated and will be ignored because '--exclude-deprecated' is set\n", chart.String()) + fmt.Printf("Chart %q is deprecated and will be ignored because '--exclude-deprecated' is set\n", chart.String()) } else { charts = append(charts, chart) } } fmt.Println() - util.PrintDelimiterLine("-") + util.PrintDelimiterLineToWriter(os.Stdout, "-") fmt.Println(" Charts to be processed:") - util.PrintDelimiterLine("-") + util.PrintDelimiterLineToWriter(os.Stdout, "-") for _, chart := range charts { fmt.Printf(" %s\n", chart) } - util.PrintDelimiterLine("-") + util.PrintDelimiterLineToWriter(os.Stdout, "-") fmt.Println() repoArgs := map[string][]string{} @@ -342,7 +341,7 @@ func (t *Testing) processCharts(action func(chart *Chart) TestResult) ([]TestRes repoExtraArgs := repoArgs[name] if err := t.helm.AddRepo(name, url, repoExtraArgs); err != nil { - return nil, errors.Wrapf(err, "Error adding repo: %s=%s", name, url) + return nil, fmt.Errorf("failed adding repo: %s=%s: %w", name, url, err) } } @@ -355,31 +354,31 @@ func (t *Testing) processCharts(action func(chart *Chart) TestResult) ([]TestRes if t.config.Upgrade { mergeBase, err := t.computeMergeBase() if err != nil { - return results, errors.Wrap(err, "Error identifying merge base") + return results, fmt.Errorf("failed identifying merge base: %w", err) } // Add worktree for the target revision - worktreePath, err := ioutil.TempDir("./", "ct_previous_revision") + worktreePath, err := os.MkdirTemp("./", "ct_previous_revision") if err != nil { - return results, errors.Wrap(err, "Could not create previous revision directory") + return results, fmt.Errorf("could not create previous revision directory: %w", err) } t.previousRevisionWorktree = worktreePath err = t.git.AddWorktree(worktreePath, mergeBase) if err != nil { - return results, errors.Wrap(err, "Could not create worktree for previous revision") + return results, fmt.Errorf("could not create worktree for previous revision: %w", err) } - defer t.git.RemoveWorktree(worktreePath) + defer t.git.RemoveWorktree(worktreePath) // nolint: errcheck for _, chart := range charts { if err := t.helm.BuildDependenciesWithArgs(t.computePreviousRevisionPath(chart.Path()), t.config.HelmDependencyExtraArgs); err != nil { // Only print error (don't exit) if building dependencies for previous revision fails. - fmt.Println(errors.Wrapf(err, "Error building dependencies for previous revision of chart '%s'\n", chart)) + fmt.Printf("failed building dependencies for previous revision of chart %q: %v\n", chart, err.Error()) } } } for _, chart := range charts { if err := t.helm.BuildDependenciesWithArgs(chart.Path(), t.config.HelmDependencyExtraArgs); err != nil { - return nil, errors.Wrapf(err, "Error building dependencies for chart '%s'", chart) + return nil, fmt.Errorf("failed building dependencies for chart %q: %w", chart, err) } result := action(chart) @@ -392,7 +391,7 @@ func (t *Testing) processCharts(action func(chart *Chart) TestResult) ([]TestRes return results, nil } - return results, errors.New("Error processing charts") + return results, fmt.Errorf("failed processing charts") } // LintCharts lints charts (changed, all, specific) depending on the configuration. @@ -412,7 +411,7 @@ func (t *Testing) LintAndInstallCharts() ([]TestResult, error) { // PrintResults writes test results to stdout. func (t *Testing) PrintResults(results []TestResult) { - util.PrintDelimiterLine("-") + util.PrintDelimiterLineToWriter(os.Stdout, "-") if results != nil { for _, result := range results { err := result.Error @@ -425,12 +424,12 @@ func (t *Testing) PrintResults(results []TestResult) { } else { fmt.Println("No chart changes detected.") } - util.PrintDelimiterLine("-") + util.PrintDelimiterLineToWriter(os.Stdout, "-") } // LintChart lints the specified chart. func (t *Testing) LintChart(chart *Chart) TestResult { - fmt.Printf("Linting chart '%s'\n", chart) + fmt.Printf("Linting chart %q\n", chart) result := TestResult{Chart: chart} @@ -483,7 +482,7 @@ func (t *Testing) LintChart(chart *Chart) TestResult { for _, valuesFile := range valuesFiles { if valuesFile != "" { - fmt.Printf("\nLinting chart with values file '%s'...\n\n", valuesFile) + fmt.Printf("\nLinting chart with values file %q...\n\n", valuesFile) } if err := t.helm.LintWithValues(chart.Path(), valuesFile); err != nil { result.Error = err @@ -531,11 +530,11 @@ func (t *Testing) UpgradeChart(chart *Chart) TestResult { if breakingChangeAllowed { if err != nil { - fmt.Println(errors.Wrap(err, fmt.Sprintf("Skipping upgrade test of '%s' because", chart))) + fmt.Printf("Skipping upgrade test of %q because: %v\n", chart, err.Error()) } return result } else if err != nil { - fmt.Printf("Error comparing chart versions for '%s'\n", chart) + fmt.Printf("Error comparing chart versions for %q\n", chart) result.Error = err return result } @@ -548,7 +547,7 @@ func (t *Testing) UpgradeChart(chart *Chart) TestResult { } func (t *Testing) doInstall(chart *Chart) error { - fmt.Printf("Installing chart '%s'...\n", chart) + fmt.Printf("Installing chart %q...\n", chart) valuesFiles := chart.ValuesFilePathsForCI() // Test with defaults if no values files are specified. @@ -558,7 +557,7 @@ func (t *Testing) doInstall(chart *Chart) error { for _, valuesFile := range valuesFiles { if valuesFile != "" { - fmt.Printf("\nInstalling chart with values file '%s'...\n\n", valuesFile) + fmt.Printf("\nInstalling chart with values file %q...\n\n", valuesFile) } // Use anonymous function. Otherwise deferred calls would pile up @@ -587,7 +586,7 @@ func (t *Testing) doInstall(chart *Chart) error { } func (t *Testing) doUpgrade(oldChart, newChart *Chart, oldChartMustPass bool) error { - fmt.Printf("Testing upgrades of chart '%s' relative to previous revision '%s'...\n", newChart, oldChart) + fmt.Printf("Testing upgrades of chart %q relative to previous revision %q...\n", newChart, oldChart) valuesFiles := oldChart.ValuesFilePathsForCI() if len(valuesFiles) == 0 { valuesFiles = append(valuesFiles, "") @@ -595,10 +594,10 @@ func (t *Testing) doUpgrade(oldChart, newChart *Chart, oldChartMustPass bool) er for _, valuesFile := range valuesFiles { if valuesFile != "" { if t.config.SkipMissingValues && !newChart.HasCIValuesFile(valuesFile) { - fmt.Printf("Upgrade testing for values file '%s' skipped because a corresponding values file was not found in %s/ci", valuesFile, newChart.Path()) + fmt.Printf("Upgrade testing for values file %q skipped because a corresponding values file was not found in %s/ci\n", valuesFile, newChart.Path()) continue } - fmt.Printf("\nInstalling chart '%s' with values file '%s'...\n\n", oldChart, valuesFile) + fmt.Printf("\nInstalling chart %q with values file %q...\n\n", oldChart, valuesFile) } // Use anonymous function. Otherwise deferred calls would pile up @@ -617,14 +616,14 @@ func (t *Testing) doUpgrade(oldChart, newChart *Chart, oldChartMustPass bool) er if oldChartMustPass { return err } - fmt.Println(errors.Wrap(err, fmt.Sprintf("Upgrade testing for release '%s' skipped because of previous revision installation error", release))) + fmt.Printf("Upgrade testing for release %q skipped because of previous revision installation error: %v\n", release, err.Error()) return nil } if err := t.testRelease(namespace, release, releaseSelector); err != nil { if oldChartMustPass { return err } - fmt.Println(errors.Wrap(err, fmt.Sprintf("Upgrade testing for release '%s' skipped because of previous revision testing error", release))) + fmt.Printf("Upgrade testing for release %q skipped because of previous revision testing error: %v\n", release, err.Error()) return nil } @@ -656,14 +655,14 @@ func (t *Testing) testRelease(namespace, release, releaseSelector string) error func (t *Testing) generateInstallConfig(chart *Chart) (namespace, release, releaseSelector string, cleanup func()) { if t.config.Namespace != "" { namespace = t.config.Namespace - release, _ = chart.CreateInstallParams(t.config.BuildId) + release, _ = chart.CreateInstallParams(t.config.BuildID) releaseSelector = fmt.Sprintf("%s=%s", t.config.ReleaseLabel, release) cleanup = func() { t.PrintEventsPodDetailsAndLogs(namespace, releaseSelector) t.helm.DeleteRelease(namespace, release) } } else { - release, namespace = chart.CreateInstallParams(t.config.BuildId) + release, namespace = chart.CreateInstallParams(t.config.BuildID) cleanup = func() { t.PrintEventsPodDetailsAndLogs(namespace, releaseSelector) t.helm.DeleteRelease(namespace, release) @@ -698,7 +697,7 @@ func (t *Testing) FindChartDirsToBeProcessed() ([]string, error) { func (t *Testing) computeMergeBase() (string, error) { err := t.git.ValidateRepository() if err != nil { - return "", errors.New("Must be in a git repository") + return "", errors.New("must be in a git repository") } return t.git.MergeBase(fmt.Sprintf("%s/%s", t.config.Remote, t.config.TargetBranch), t.config.Since) } @@ -715,7 +714,7 @@ func (t *Testing) ComputeChangedChartDirectories() ([]string, error) { allChangedChartFiles, err := t.git.ListChangedFilesInDirs(mergeBase, cfg.ChartDirs...) if err != nil { - return nil, errors.Wrap(err, "Error creating diff") + return nil, fmt.Errorf("failed creating diff: %w", err) } var changedChartDirs []string @@ -726,7 +725,7 @@ func (t *Testing) ComputeChangedChartDirectories() ([]string, error) { } dir := filepath.Dir(file) // Make sure directory is really a chart directory - chartDir, err := t.chartUtils.LookupChartDir(cfg.ChartDirs, dir) + chartDir, err := t.utils.LookupChartDir(cfg.ChartDirs, dir) chartDirElement := strings.Split(chartDir, "/") if err == nil { if len(chartDirElement) > 1 { @@ -740,7 +739,7 @@ func (t *Testing) ComputeChangedChartDirectories() ([]string, error) { changedChartDirs = append(changedChartDirs, chartDir) } } else { - fmt.Fprintf(os.Stderr, "Directory '%s' is not a valid chart directory. Skipping...\n", dir) + fmt.Fprintf(os.Stderr, "Directory %q is not a valid chart directory. Skipping...\n", dir) } } @@ -756,11 +755,11 @@ func (t *Testing) ReadAllChartDirectories() ([]string, error) { for _, chartParentDir := range cfg.ChartDirs { dirs, err := t.directoryLister.ListChildDirs(chartParentDir, func(dir string) bool { - _, err := t.chartUtils.LookupChartDir(cfg.ChartDirs, dir) + _, err := t.utils.LookupChartDir(cfg.ChartDirs, dir) return err == nil && !util.StringSliceContains(cfg.ExcludedCharts, filepath.Base(dir)) }) if err != nil { - return nil, errors.Wrap(err, "Error reading chart directories") + return nil, fmt.Errorf("failed reading chart directories: %w", err) } chartDirs = append(chartDirs, dirs...) } @@ -770,7 +769,7 @@ func (t *Testing) ReadAllChartDirectories() ([]string, error) { // CheckVersionIncrement checks that the new chart version is greater than the old one using semantic version comparison. func (t *Testing) CheckVersionIncrement(chart *Chart) error { - fmt.Printf("Checking chart '%s' for a version bump...\n", chart) + fmt.Printf("Checking chart %q for a version bump...\n", chart) oldVersion, err := t.GetOldChartVersion(chart.Path()) if err != nil { @@ -793,7 +792,7 @@ func (t *Testing) CheckVersionIncrement(chart *Chart) error { } if result >= 0 { - return errors.New("Chart version not ok. Needs a version bump!") + return errors.New("chart version not ok. Needs a version bump! ") } fmt.Println("Chart version ok.") @@ -827,12 +826,12 @@ func (t *Testing) GetOldChartVersion(chartPath string) (string, error) { chartYamlContents, err := t.git.Show(chartYamlFile, cfg.Remote, cfg.TargetBranch) if err != nil { - return "", errors.Wrap(err, "Error reading old Chart.yaml") + return "", fmt.Errorf("failed reading old Chart.yaml: %w", err) } chartYaml, err := util.UnmarshalChartYaml([]byte(chartYamlContents)) if err != nil { - return "", errors.Wrap(err, "Error reading old chart version") + return "", fmt.Errorf("failed reading old chart version: %w", err) } return chartYaml.Version, nil @@ -847,22 +846,22 @@ func (t *Testing) ValidateMaintainers(chart *Chart) error { if chartYaml.Deprecated { if len(chartYaml.Maintainers) > 0 { - return errors.New("Deprecated chart must not have maintainers") + return errors.New("deprecated chart must not have maintainers") } return nil } if len(chartYaml.Maintainers) == 0 { - return errors.New("Chart doesn't have maintainers") + return errors.New("chart doesn't have maintainers") } - repoUrl, err := t.git.GetUrlForRemote(t.config.Remote) + repoURL, err := t.git.GetURLForRemote(t.config.Remote) if err != nil { return err } for _, maintainer := range chartYaml.Maintainers { - if err := t.accountValidator.Validate(repoUrl, maintainer.Name); err != nil { + if err := t.accountValidator.Validate(repoURL, maintainer.Name); err != nil { return err } } @@ -871,7 +870,7 @@ func (t *Testing) ValidateMaintainers(chart *Chart) error { } func (t *Testing) PrintEventsPodDetailsAndLogs(namespace string, selector string) { - util.PrintDelimiterLine("=") + util.PrintDelimiterLineToWriter(os.Stdout, "=") printDetails(namespace, "Events of namespace", ".", func(item string) error { return t.kubectl.GetEvents(namespace) @@ -909,7 +908,7 @@ func (t *Testing) PrintEventsPodDetailsAndLogs(namespace string, selector string containers, err := t.kubectl.GetContainers(namespace, pod) if err != nil { - fmt.Println("Error printing logs:", err) + fmt.Printf("failed printing logs: %v\n", err.Error()) return } @@ -920,24 +919,24 @@ func (t *Testing) PrintEventsPodDetailsAndLogs(namespace string, selector string containers...) } - util.PrintDelimiterLine("=") + util.PrintDelimiterLineToWriter(os.Stdout, "=") } func printDetails(resource string, text string, delimiterChar string, printFunc func(item string) error, items ...string) { for _, item := range items { item = strings.Trim(item, "'") - util.PrintDelimiterLine(delimiterChar) + util.PrintDelimiterLineToWriter(os.Stdout, delimiterChar) fmt.Printf("==> %s %s\n", text, resource) - util.PrintDelimiterLine(delimiterChar) + util.PrintDelimiterLineToWriter(os.Stdout, delimiterChar) if err := printFunc(item); err != nil { fmt.Println("Error printing details:", err) return } - util.PrintDelimiterLine(delimiterChar) + util.PrintDelimiterLineToWriter(os.Stdout, delimiterChar) fmt.Printf("<== %s %s\n", text, resource) - util.PrintDelimiterLine(delimiterChar) + util.PrintDelimiterLineToWriter(os.Stdout, delimiterChar) } } diff --git a/pkg/chart/chart_test.go b/pkg/chart/chart_test.go index 2f05a311..78cf8d1f 100644 --- a/pkg/chart/chart_test.go +++ b/pkg/chart/chart_test.go @@ -21,7 +21,6 @@ import ( "github.com/helm/chart-testing/v3/pkg/config" "github.com/helm/chart-testing/v3/pkg/util" - "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) @@ -63,7 +62,7 @@ func (g fakeGit) RemoveWorktree(path string) error { return nil } -func (g fakeGit) GetUrlForRemote(remote string) (string, error) { +func (g fakeGit) GetURLForRemote(remote string) (string, error) { return "git@github.com/helm/chart-testing", nil } @@ -77,7 +76,7 @@ func (v fakeAccountValidator) Validate(repoDomain string, account string) error if strings.HasPrefix(account, "valid") { return nil } - return errors.New(fmt.Sprintf("Error validating account: %s", account)) + return fmt.Errorf("failed validating account: %s", account) } type fakeLinter struct { @@ -145,7 +144,7 @@ func newTestingMock(cfg config.Configuration) Testing { config: cfg, directoryLister: util.DirectoryLister{}, git: fakeGit{}, - chartUtils: util.ChartUtils{}, + utils: util.Utils{}, accountValidator: fakeAccountValidator{}, linter: fakeMockLinter, helm: new(fakeHelm), @@ -299,7 +298,6 @@ func TestLintChartSchemaValidation(t *testing.T) { runTests(true, 0, 1) runTests(false, 0, 0) - } func TestLintYamlValidation(t *testing.T) { diff --git a/pkg/chart/integration_test.go b/pkg/chart/integration_test.go index 9d5f881f..5322d0f5 100644 --- a/pkg/chart/integration_test.go +++ b/pkg/chart/integration_test.go @@ -38,7 +38,7 @@ func newTestingHelmIntegration(cfg config.Configuration, extraSetArgs string) Te config: cfg, directoryLister: util.DirectoryLister{}, git: fakeGit{}, - chartUtils: util.ChartUtils{}, + utils: util.Utils{}, accountValidator: fakeAccountValidator{}, linter: fakeMockLinter, helm: tool.NewHelm(procExec, extraArgs, strings.Fields(extraSetArgs)), @@ -121,7 +121,7 @@ func TestUpgradeChart(t *testing.T) { Upgrade: true, } ct := newTestingHelmIntegration(cfg, "") - processError := fmt.Errorf("Error waiting for process: exit status 1") + processError := fmt.Errorf("failed waiting for process: exit status 1") cases := []testCase{ { diff --git a/pkg/config/config.go b/pkg/config/config.go index 7113761d..1c849c8f 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -15,6 +15,7 @@ package config import ( + "errors" "fmt" "os" "path/filepath" @@ -25,7 +26,6 @@ import ( "github.com/mitchellh/go-homedir" "github.com/helm/chart-testing/v3/pkg/util" - "github.com/pkg/errors" "github.com/spf13/cobra" flag "github.com/spf13/pflag" "github.com/spf13/viper" @@ -45,7 +45,7 @@ type Configuration struct { Remote string `mapstructure:"remote"` TargetBranch string `mapstructure:"target-branch"` Since string `mapstructure:"since"` - BuildId string `mapstructure:"build-id"` + BuildID string `mapstructure:"build-id"` LintConf string `mapstructure:"lint-conf"` ChartYamlSchema string `mapstructure:"chart-yaml-schema"` ValidateMaintainers bool `mapstructure:"validate-maintainers"` @@ -73,14 +73,14 @@ type Configuration struct { func LoadConfiguration(cfgFile string, cmd *cobra.Command, printConfig bool) (*Configuration, error) { v := viper.New() - v.SetDefault("kubectl-timeout", time.Duration(30*time.Second)) + v.SetDefault("kubectl-timeout", 30*time.Second) cmd.Flags().VisitAll(func(flag *flag.Flag) { flagName := flag.Name if flagName != "config" && flagName != "help" { if err := v.BindPFlag(flagName, flag); err != nil { // can't really happen - panic(fmt.Sprintln(errors.Wrapf(err, "Error binding flag '%s'", flagName))) + panic(fmt.Sprintf("failed binding flag %q: %v\n", flagName, err.Error())) } } }) @@ -105,7 +105,7 @@ func LoadConfiguration(cfgFile string, cmd *cobra.Command, printConfig bool) (*C if err := v.ReadInConfig(); err != nil { if cfgFile != "" { // Only error out for specified config file. Ignore for default locations. - return nil, errors.Wrap(err, "Error loading config file") + return nil, fmt.Errorf("failed loading config file: %w", err) } } else { if printConfig { @@ -118,7 +118,7 @@ func LoadConfiguration(cfgFile string, cmd *cobra.Command, printConfig bool) (*C cfg := &Configuration{} if err := v.Unmarshal(cfg); err != nil { - return nil, errors.Wrap(err, "Error unmarshaling configuration") + return nil, fmt.Errorf("failed unmarshaling configuration: %w", err) } if cfg.ProcessAllCharts && len(cfg.Charts) > 0 { @@ -202,5 +202,5 @@ func findConfigFile(fileName string) (string, error) { } } - return "", errors.New(fmt.Sprintf("Config file not found: %s", fileName)) + return "", fmt.Errorf("config file not found: %s", fileName) } diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 00871925..4026f4ed 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -40,7 +40,7 @@ func loadAndAssertConfigFromFile(t *testing.T, configFile string) { require.Equal(t, "origin", cfg.Remote) require.Equal(t, "main", cfg.TargetBranch) - require.Equal(t, "pr-42", cfg.BuildId) + require.Equal(t, "pr-42", cfg.BuildID) require.Equal(t, "my-lint-conf.yaml", cfg.LintConf) require.Equal(t, "my-chart-yaml-schema.yaml", cfg.ChartYamlSchema) require.Equal(t, true, cfg.ValidateMaintainers) diff --git a/pkg/exec/exec.go b/pkg/exec/exec.go index 3ab4bec9..b0869b37 100644 --- a/pkg/exec/exec.go +++ b/pkg/exec/exec.go @@ -23,7 +23,6 @@ import ( "strings" "github.com/helm/chart-testing/v3/pkg/util" - "github.com/pkg/errors" ) type ProcessExecutor struct { @@ -54,7 +53,7 @@ func (p ProcessExecutor) RunProcessInDirAndCaptureOutput(workingDirectory string bytes, err := cmd.CombinedOutput() if err != nil { - return "", errors.Wrap(err, "Error running process") + return "", fmt.Errorf("failed running process: %w", err) } return strings.TrimSpace(string(bytes)), nil } @@ -69,7 +68,7 @@ func (p ProcessExecutor) RunProcessInDirAndCaptureStdout(workingDirectory string bytes, err := cmd.Output() if err != nil { - return "", errors.Wrap(err, "Error running process") + return "", fmt.Errorf("failed running process: %w", err) } return strings.TrimSpace(string(bytes)), nil } @@ -82,12 +81,12 @@ func (p ProcessExecutor) RunProcess(executable string, execArgs ...interface{}) outReader, err := cmd.StdoutPipe() if err != nil { - return errors.Wrap(err, "Error getting StdoutPipe for command") + return fmt.Errorf("failed getting StdoutPipe for command: %w", err) } errReader, err := cmd.StderrPipe() if err != nil { - return errors.Wrap(err, "Error getting StderrPipe for command") + return fmt.Errorf("failed getting StderrPipe for command: %w", err) } scanner := bufio.NewScanner(io.MultiReader(outReader, errReader)) @@ -99,12 +98,12 @@ func (p ProcessExecutor) RunProcess(executable string, execArgs ...interface{}) err = cmd.Start() if err != nil { - return errors.Wrap(err, "Error running process") + return fmt.Errorf("failed running process: %w", err) } err = cmd.Wait() if err != nil { - return errors.Wrap(err, "Error waiting for process") + return fmt.Errorf("failed waiting for process: %w", err) } return nil @@ -116,7 +115,7 @@ func (p ProcessExecutor) CreateProcess(executable string, execArgs ...interface{ fmt.Println(">>>", executable, strings.Join(args, " ")) } if err != nil { - return nil, errors.Wrap(err, "Invalid arguments supplied") + return nil, fmt.Errorf("invalid arguments supplied: %w", err) } cmd := exec.Command(executable, args...) @@ -128,25 +127,25 @@ type fn func(port int) error func (p ProcessExecutor) RunWithProxy(withProxy fn) error { randomPort, err := util.GetRandomPort() if err != nil { - return errors.Wrap(err, "Could not find a free port for running 'kubectl proxy'") + return fmt.Errorf("could not find a free port for running 'kubectl proxy': %w", err) } fmt.Printf("Running 'kubectl proxy' on port %d\n", randomPort) cmdProxy, err := p.CreateProcess("kubectl", "proxy", fmt.Sprintf("--port=%d", randomPort)) if err != nil { - return errors.Wrap(err, "Error creating the 'kubectl proxy' process") + return fmt.Errorf("failed creating the 'kubectl proxy' process: %w", err) } err = cmdProxy.Start() if err != nil { - return errors.Wrap(err, "Error starting the 'kubectl proxy' process") + return fmt.Errorf("failed starting the 'kubectl proxy' process: %w", err) } err = withProxy(randomPort) - cmdProxy.Process.Signal(os.Kill) + _ = cmdProxy.Process.Signal(os.Kill) if err != nil { - return errors.Wrap(err, "Error running command with proxy") + return fmt.Errorf("failed running command with proxy: %w", err) } return nil diff --git a/pkg/tool/account.go b/pkg/tool/account.go index c1433fa2..26de6f10 100644 --- a/pkg/tool/account.go +++ b/pkg/tool/account.go @@ -18,8 +18,6 @@ import ( "fmt" "net/http" "regexp" - - "github.com/pkg/errors" ) type AccountValidator struct{} @@ -32,12 +30,12 @@ func (v AccountValidator) Validate(repoURL string, account string) error { return err } url := fmt.Sprintf("https://%s/%s", domain, account) - response, err := http.Head(url) + response, err := http.Head(url) // nolint: gosec if err != nil { - return errors.Wrap(err, "Error validating maintainers") + return fmt.Errorf("failed validating maintainers: %w", err) } if response.StatusCode != 200 { - return fmt.Errorf("Error validating maintainer '%s': %s", account, response.Status) + return fmt.Errorf("failed validating maintainer %q: %s", account, response.Status) } return nil } @@ -46,7 +44,7 @@ func parseOutGitRepoDomain(repoURL string) (string, error) { // This works for GitHub, Bitbucket, and Gitlab submatch := repoDomainPattern.FindStringSubmatch(repoURL) if submatch == nil || len(submatch) < 2 { - return "", fmt.Errorf("Could not parse git repository domain for '%s'", repoURL) + return "", fmt.Errorf("could not parse git repository domain for %q", repoURL) } return submatch[1], nil } diff --git a/pkg/tool/account_test.go b/pkg/tool/account_test.go index 498d5e04..30a03f5f 100644 --- a/pkg/tool/account_test.go +++ b/pkg/tool/account_test.go @@ -10,7 +10,7 @@ import ( func TestParseOutGitDomain(t *testing.T) { var testDataSlice = []struct { name string - repoUrl string + repoURL string expected string err error }{ @@ -23,12 +23,12 @@ func TestParseOutGitDomain(t *testing.T) { {"Bitbucket SSH", "git@bitbucket.com:foo/bar", "bitbucket.com", nil}, {"Bitbucket HTTPS", "https://bitbucket.com/foo/bar", "bitbucket.com", nil}, {"Bitbucket HTTPS with username/password", "https://user:pass@bitbucket.com/foo/bar", "bitbucket.com", nil}, - {"Invalid", "foo/bar", "", fmt.Errorf("Could not parse git repository domain for 'foo/bar'")}, + {"Invalid", "foo/bar", "", fmt.Errorf("could not parse git repository domain for \"foo/bar\"")}, } for _, testData := range testDataSlice { t.Run(testData.name, func(t *testing.T) { - actual, err := parseOutGitRepoDomain(testData.repoUrl) + actual, err := parseOutGitRepoDomain(testData.repoURL) assert.Equal(t, err, testData.err) assert.Equal(t, testData.expected, actual) }) diff --git a/pkg/tool/cmdexecutor_test.go b/pkg/tool/cmdexecutor_test.go index 21cb6ea9..67fb5f23 100644 --- a/pkg/tool/cmdexecutor_test.go +++ b/pkg/tool/cmdexecutor_test.go @@ -69,8 +69,8 @@ func TestCmdTemplateExecutor_RunCommand(t *testing.T) { if err := templateExecutor.RunCommand(tt.args.cmdTemplate, tt.args.data); (err != nil) != tt.wantErr { t.Errorf("RunCommand() error = %v, wantErr %v", err, tt.wantErr) } - tt.validate(t, processExecutor) + tt.validate(t, processExecutor) }) } } diff --git a/pkg/tool/git.go b/pkg/tool/git.go index 361a6888..1fe5551f 100644 --- a/pkg/tool/git.go +++ b/pkg/tool/git.go @@ -19,7 +19,6 @@ import ( "strings" "github.com/helm/chart-testing/v3/pkg/exec" - "github.com/pkg/errors" ) type Git struct { @@ -59,7 +58,7 @@ func (g Git) ListChangedFilesInDirs(commit string, dirs ...string) ([]string, er changedChartFilesString, err := g.exec.RunProcessAndCaptureOutput("git", "diff", "--find-renames", "--name-only", commit, "--", dirs) if err != nil { - return nil, errors.Wrap(err, "Error creating diff") + return nil, fmt.Errorf("failed creating diff: %w", err) } if changedChartFilesString == "" { return nil, nil @@ -67,7 +66,7 @@ func (g Git) ListChangedFilesInDirs(commit string, dirs ...string) ([]string, er return strings.Split(changedChartFilesString, "\n"), nil } -func (g Git) GetUrlForRemote(remote string) (string, error) { +func (g Git) GetURLForRemote(remote string) (string, error) { return g.exec.RunProcessAndCaptureOutput("git", "ls-remote", "--get-url", remote) } diff --git a/pkg/tool/helm.go b/pkg/tool/helm.go index 44afd470..f7715d64 100644 --- a/pkg/tool/helm.go +++ b/pkg/tool/helm.go @@ -83,7 +83,7 @@ func (h Helm) Test(namespace string, release string) error { } func (h Helm) DeleteRelease(namespace string, release string) { - fmt.Printf("Deleting release '%s'...\n", release) + fmt.Printf("Deleting release %q...\n", release) if err := h.exec.RunProcess("helm", "uninstall", release, "--namespace", namespace, h.extraArgs); err != nil { fmt.Println("Error deleting Helm release:", err) } diff --git a/pkg/tool/kubectl.go b/pkg/tool/kubectl.go index d2021e58..5ad72f09 100644 --- a/pkg/tool/kubectl.go +++ b/pkg/tool/kubectl.go @@ -3,6 +3,7 @@ package tool import ( "bytes" "encoding/json" + "errors" "fmt" "net/http" "strings" @@ -10,7 +11,6 @@ import ( "github.com/hashicorp/go-retryablehttp" "github.com/helm/chart-testing/v3/pkg/exec" - "github.com/pkg/errors" ) type Kubectl struct { @@ -27,7 +27,7 @@ func NewKubectl(exec exec.ProcessExecutor, timeout time.Duration) Kubectl { // CreateNamespace creates a new namespace with the given name. func (k Kubectl) CreateNamespace(namespace string) error { - fmt.Printf("Creating namespace '%s'...\n", namespace) + fmt.Printf("Creating namespace %q...\n", namespace) return k.exec.RunProcess("kubectl", fmt.Sprintf("--request-timeout=%s", k.timeout), "create", "namespace", namespace) @@ -36,17 +36,17 @@ func (k Kubectl) CreateNamespace(namespace string) error { // DeleteNamespace deletes the specified namespace. If the namespace does not terminate within 120s, pods running in the // namespace and, eventually, the namespace itself are force-deleted. func (k Kubectl) DeleteNamespace(namespace string) { - fmt.Printf("Deleting namespace '%s'...\n", namespace) + fmt.Printf("Deleting namespace %q...\n", namespace) timeoutSec := "180s" err := k.exec.RunProcess("kubectl", fmt.Sprintf("--request-timeout=%s", k.timeout), "delete", "namespace", namespace, "--timeout", timeoutSec) if err != nil { - fmt.Printf("Namespace '%s' did not terminate after %s.\n", namespace, timeoutSec) + fmt.Printf("Namespace %q did not terminate after %s.\n", namespace, timeoutSec) } if k.getNamespace(namespace) { - fmt.Printf("Namespace '%s' did not terminate after %s.\n", namespace, timeoutSec) + fmt.Printf("Namespace %q did not terminate after %s.\n", namespace, timeoutSec) fmt.Println("Force-deleting everything...") err = k.exec.RunProcess("kubectl", @@ -93,7 +93,7 @@ func (k Kubectl) forceNamespaceDeletion(namespace string) error { // Remove finalizer from the namespace fun := func(port int) error { - fmt.Printf("Removing finalizers from namespace '%s'...\n", namespace) + fmt.Printf("Removing finalizers from namespace %q...\n", namespace) k8sURL := fmt.Sprintf("http://127.0.0.1:%d/api/v1/namespaces/%s/finalize", port, namespace) req, err := retryablehttp.NewRequest("PUT", k8sURL, bytes.NewReader(namespaceUpdateBytes)) @@ -107,7 +107,7 @@ func (k Kubectl) forceNamespaceDeletion(namespace string) error { client := retryablehttp.NewClient() client.Logger = nil if resp, err := client.Do(req); err != nil { - return errors.Wrap(err, errMsg) + return fmt.Errorf("%s:%w", errMsg, err) } else if resp.StatusCode != http.StatusOK { return errors.New(errMsg) } @@ -117,7 +117,7 @@ func (k Kubectl) forceNamespaceDeletion(namespace string) error { err = k.exec.RunWithProxy(fun) if err != nil { - return errors.Wrapf(err, "Cannot force-delete namespace '%s'", namespace) + return fmt.Errorf("cannot force-delete namespace %q: %w", namespace, err) } // Give it some more time to be deleted by K8s @@ -128,11 +128,11 @@ func (k Kubectl) forceNamespaceDeletion(namespace string) error { fmt.Sprintf("--request-timeout=%s", k.timeout), "get", "namespace", namespace) if err != nil { - fmt.Printf("Namespace '%s' terminated.\n", namespace) + fmt.Printf("Namespace %q terminated.\n", namespace) return nil } - fmt.Printf("Force-deleting namespace '%s'...\n", namespace) + fmt.Printf("Force-deleting namespace %q...\n", namespace) err = k.exec.RunProcess("kubectl", fmt.Sprintf("--request-timeout=%s", k.timeout), "delete", "namespace", namespace, "--force", "--grace-period=0", @@ -250,7 +250,7 @@ func (k Kubectl) getNamespace(namespace string) bool { fmt.Sprintf("--request-timeout=%s", k.timeout), "get", "namespace", namespace) if err != nil { - fmt.Printf("Namespace '%s' terminated.\n", namespace) + fmt.Printf("Namespace %q terminated.\n", namespace) return false } diff --git a/pkg/util/util.go b/pkg/util/util.go index c0405212..d3f1974b 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -15,9 +15,10 @@ package util import ( + "errors" "fmt" "io" - "io/ioutil" + "io/fs" "math/rand" "net" "os" @@ -28,7 +29,6 @@ import ( "github.com/Masterminds/semver" "github.com/hashicorp/go-multierror" - "github.com/pkg/errors" "gopkg.in/yaml.v2" ) @@ -70,7 +70,7 @@ func doFlatten(result []string, items interface{}) ([]string, error) { } } default: - return nil, errors.New(fmt.Sprintf("Flatten does not support %T", v)) + return nil, fmt.Errorf("flatten does not support %T", v) } return result, err @@ -97,7 +97,7 @@ func RandomString(length int) string { n := len(chars) bytes := make([]byte, length) for i := range bytes { - bytes[i] = chars[rand.Intn(n)] + bytes[i] = chars[rand.Intn(n)] // nolint: gosec } return string(bytes) } @@ -106,10 +106,18 @@ type DirectoryLister struct{} // ListChildDirs lists subdirectories of parentDir matching the test function. func (l DirectoryLister) ListChildDirs(parentDir string, test func(dir string) bool) ([]string, error) { - fileInfos, err := ioutil.ReadDir(parentDir) + entries, err := os.ReadDir(parentDir) if err != nil { return nil, err } + fileInfos := make([]fs.FileInfo, 0, len(entries)) + for _, entry := range entries { + info, err := entry.Info() + if err != nil { + return nil, err + } + fileInfos = append(fileInfos, info) + } var dirs []string for _, dir := range fileInfos { @@ -123,9 +131,9 @@ func (l DirectoryLister) ListChildDirs(parentDir string, test func(dir string) b return dirs, nil } -type ChartUtils struct{} +type Utils struct{} -func (u ChartUtils) LookupChartDir(chartDirs []string, dir string) (string, error) { +func (u Utils) LookupChartDir(chartDirs []string, dir string) (string, error) { for _, chartDir := range chartDirs { currentDir := dir for { @@ -154,9 +162,9 @@ func (u ChartUtils) LookupChartDir(chartDirs []string, dir string) (string, erro // and return a newly allocated ChartYaml object. If no Chart.yaml is present // or there is an error unmarshaling the file contents, an error will be returned. func ReadChartYaml(dir string) (*ChartYaml, error) { - yamlBytes, err := ioutil.ReadFile(filepath.Join(dir, "Chart.yaml")) + yamlBytes, err := os.ReadFile(filepath.Join(dir, "Chart.yaml")) if err != nil { - return nil, errors.Wrap(err, "Could not read 'Chart.yaml'") + return nil, fmt.Errorf("could not read 'Chart.yaml': %w", err) } return UnmarshalChartYaml(yamlBytes) } @@ -166,7 +174,7 @@ func ReadChartYaml(dir string) (*ChartYaml, error) { func UnmarshalChartYaml(yamlBytes []byte) (*ChartYaml, error) { chartYaml := &ChartYaml{} if err := yaml.Unmarshal(yamlBytes, chartYaml); err != nil { - return nil, errors.Wrap(err, "Could not unmarshal 'Chart.yaml'") + return nil, fmt.Errorf("could not unmarshal 'Chart.yaml': %w", err) } return chartYaml, nil } @@ -174,11 +182,11 @@ func UnmarshalChartYaml(yamlBytes []byte) (*ChartYaml, error) { func CompareVersions(left string, right string) (int, error) { leftVersion, err := semver.NewVersion(left) if err != nil { - return 0, errors.Wrap(err, "Error parsing semantic version") + return 0, fmt.Errorf("failed parsing semantic version: %w", err) } rightVersion, err := semver.NewVersion(right) if err != nil { - return 0, errors.Wrap(err, "Error parsing semantic version") + return 0, fmt.Errorf("failed parsing semantic version: %w", err) } return leftVersion.Compare(rightVersion), nil } @@ -186,11 +194,11 @@ func CompareVersions(left string, right string) (int, error) { func BreakingChangeAllowed(left string, right string) (bool, error) { leftVersion, err := semver.NewVersion(left) if err != nil { - return false, errors.Wrap(err, "Error parsing semantic version") + return false, fmt.Errorf("failed parsing semantic version: %w", err) } rightVersion, err := semver.NewVersion(right) if err != nil { - return false, errors.Wrap(err, "Error parsing semantic version") + return false, fmt.Errorf("failed parsing semantic version: %w", err) } constraintOp := "^" @@ -199,7 +207,7 @@ func BreakingChangeAllowed(left string, right string) (bool, error) { } c, err := semver.NewConstraint(fmt.Sprintf("%s %s", constraintOp, leftVersion.String())) if err != nil { - return false, errors.Wrap(err, "Error parsing semantic version constraint") + return false, fmt.Errorf("failed parsing semantic version constraint: %w", err) } minor, reasons := c.Validate(rightVersion) @@ -210,11 +218,6 @@ func BreakingChangeAllowed(left string, right string) (bool, error) { return !minor, err } -// Deprecated: To be removed in v4. Use PrintDelimiterLineToWriter instead. -func PrintDelimiterLine(delimiterChar string) { - PrintDelimiterLineToWriter(os.Stdout, delimiterChar) -} - func PrintDelimiterLineToWriter(w io.Writer, delimiterChar string) { delim := make([]string, 120) for i := 0; i < 120; i++ { @@ -235,8 +238,8 @@ func SanitizeName(s string, maxLength int) string { } func GetRandomPort() (int, error) { - listener, err := net.Listen("tcp", ":0") - defer listener.Close() + listener, err := net.Listen("tcp", ":0") // nolint: gosec + defer listener.Close() // nolint: staticcheck if err != nil { return 0, err }