diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 080ba37e..afed6b46 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -14,10 +14,10 @@ jobs: lint: runs-on: ubuntu-24.04 steps: - - uses: actions/setup-go@v2.1.4 + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 with: - go-version: 1.21 - - uses: actions/checkout@v2.4.0 + go-version-file: go.mod - name: "Lint the code" run: make lint - name: "Verify generate" diff --git a/.golangci.yml b/.golangci.yml index 40b090ce..25464247 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -2,6 +2,7 @@ version: "2" linters: enable: + - arangolint - asasalint - asciicheck - bidichk @@ -15,6 +16,7 @@ linters: - dupl - dupword - durationcheck + - embeddedstructfieldcheck - errcheck - errchkjson - errname @@ -24,6 +26,8 @@ linters: - forcetypeassert - ginkgolinter - gocheckcompilerdirectives + - godoclint + - godot - gochecknoinits - gochecksumtype - goconst @@ -37,9 +41,12 @@ linters: - govet - grouper - iface + - inamedparam - importas - ineffassign - interfacebloat + - intrange + - iotamixing - lll - loggercheck - makezero @@ -67,6 +74,7 @@ linters: - tparallel - unconvert - unparam + - unqueryvet - unused - usestdlibvars - usetesting @@ -78,36 +86,67 @@ linters: # These linters are disabled ONLY because fixing/investigating their complaints initially was too overwhelming. # We SHOULD try and evaluate each of them eventually and either fix their reports # or comment here on why we decided to not listen to them. + # 15 issues: many functions exceed default cyclomatic complexity threshold - cyclop + # 50 issues: needs allowlist configuration for all imports - depguard + # 50 issues: requires wrapping all errors with fmt.Errorf - err113 + # 6 issues: requires error type assertions to use errors.As/errors.Is - errorlint + # 50 issues: requires initializing every struct field explicitly - exhaustruct + # 6 issues: forbids fmt.Print*/os.Stdout usage - forbidigo + # 18 issues: enforces function declaration ordering within files + - funcorder + # 28 issues: many functions exceed default length limit - funlen + # 15 issues: flags all package-level variables + - gochecknoglobals + # 4 issues: similar to cyclop, flags high cognitive complexity - gocognit - - godot + # 9 issues: flags TODO/FIXME comments - godox + # 11 issues: flags potential security issues (hardcoded credentials, weak crypto, etc.) - gosec - - inamedparam - - intrange + # 28 issues: forbids returning interfaces - ireturn - - gochecknoglobals + # 2 issues: flags functions with low maintainability index - maintidx + # 20 issues: flags magic numbers throughout the code - mnd + # 7 issues: suggests using modern Go idioms (e.g. slices.Contains) + - modernize + # 4 issues: requires struct tags on marshaled types - musttag + # 7 issues: flags deeply nested if statements - nestif + # 3 issues: flags functions returning both nil error and nil value - nilnil + # 7 issues: requires blank lines before return/branch statements - nlreturn + # 3 issues: forbids inline error handling (if err := ...; err != nil) + - noinlineerr + # 13 issues: forbids named return values - nonamedreturns + # 50 issues: requires t.Parallel() in every test - paralleltest + # 8 issues: suggests replacing fmt.Sprintf with faster alternatives - perfsprint + # 4 issues: suggests preallocating slices - prealloc + # 27 issues: enforces struct tag alignment - tagalign + # 27 issues: enforces testify best practices - testifylint + # 31 issues: requires using separate _test packages - testpackage + # 6 issues: requires t.Helper() in test helper functions - thelper + # 50 issues: enforces minimum variable name length - varnamelen + # 50 issues: requires wrapping errors from external packages - wrapcheck settings: errcheck: diff --git a/Makefile b/Makefile index 2f681f9a..e4d14248 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ BUILD_DATE := $(shell date -u -d "@$SOURCE_DATE_EPOCH" "+${DATE_FMT}" 2>/dev/nul LDFLAGS := -X ${GIT_VERSION_PATH}=${GIT_VERSION} -X ${GIT_COMMIT_PATH}=${GIT_COMMIT} -X ${BUILD_DATE_PATH}=${BUILD_DATE} # Please update the list of linters in .golagci.yml when bumping the version. -GOLANGCI_LINT_VER = 2.7.2 +GOLANGCI_LINT_VER = 2.11.4 # ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. ENVTEST_K8S_VERSION ?= 1.25.0 diff --git a/internal/assert/assert.go b/internal/assert/assert.go index f2e705b8..277296c3 100644 --- a/internal/assert/assert.go +++ b/internal/assert/assert.go @@ -16,7 +16,7 @@ import ( "github.com/kudobuilder/kuttl/internal/step" ) -// Assert checks all provided assert files against a namespace. Upon assert failure, it prints the failures and returns an error +// Assert checks all provided assert files against a namespace. Upon assert failure, it prints the failures and returns an error. func Assert(namespace string, timeout int, assertFiles ...string) error { var objects []client.Object @@ -31,7 +31,7 @@ func Assert(namespace string, timeout int, assertFiles ...string) error { s := setupStep() var testErrors []error - for i := 0; i < timeout; i++ { + for range timeout { // start fresh testErrors = []error{} for _, expected := range objects { @@ -56,7 +56,7 @@ func Assert(namespace string, timeout int, assertFiles ...string) error { return errors.New("asserts not valid") } -// Errors checks all provided errors files against a namespace. Upon assert failure, it prints the failures and returns an error +// Errors checks all provided errors files against a namespace. Upon assert failure, it prints the failures and returns an error. func Errors(namespace string, timeout int, errorFiles ...string) error { var objects []client.Object @@ -71,7 +71,7 @@ func Errors(namespace string, timeout int, errorFiles ...string) error { s := setupStep() var testErrors []error - for i := 0; i < timeout; i++ { + for range timeout { // start fresh testErrors = []error{} for _, expected := range objects { diff --git a/internal/assert/dummy_test.go b/internal/assert/dummy_test.go index 1f4ff6b7..714fd109 100644 --- a/internal/assert/dummy_test.go +++ b/internal/assert/dummy_test.go @@ -2,7 +2,7 @@ package assert import "testing" -// TestDummy is a no-op test to satisfy coverage tools +// TestDummy is a no-op test to satisfy coverage tools. func TestDummy(_ *testing.T) { // This test exists only to ensure the package is recognized by go test // and to avoid "go: no such tool 'covdata'" warnings diff --git a/internal/expressions/dummy_test.go b/internal/expressions/dummy_test.go index 51c32083..e99a1d0c 100644 --- a/internal/expressions/dummy_test.go +++ b/internal/expressions/dummy_test.go @@ -2,7 +2,7 @@ package expressions import "testing" -// TestDummy is a no-op test to satisfy coverage tools +// TestDummy is a no-op test to satisfy coverage tools. func TestDummy(_ *testing.T) { // This test exists only to ensure the package is recognized by go test // and to avoid "go: no such tool 'covdata'" warnings diff --git a/internal/file/files.go b/internal/file/files.go index 625f0d6f..379c9c7a 100644 --- a/internal/file/files.go +++ b/internal/file/files.go @@ -28,7 +28,7 @@ func ToObjects(paths []string) ([]client.Object, error) { } // FromPath from a file or dir path returns an array of flat file paths. -// pattern is a filepath.Match pattern to limit files to a pattern +// pattern is a filepath.Match pattern to limit files to a pattern. func FromPath(path, pattern string) ([]string, error) { files := []string{} @@ -61,7 +61,7 @@ func FromPath(path, pattern string) ([]string, error) { return files, nil } -// TrimExt removes the ext of a file path, foo.tar == foo +// TrimExt removes the ext of a file path, foo.tar == foo. func TrimExt(path string) string { return strings.TrimSuffix(path, filepath.Ext(path)) } diff --git a/internal/file/tar.go b/internal/file/tar.go index fb3ee3f5..f8e33751 100644 --- a/internal/file/tar.go +++ b/internal/file/tar.go @@ -10,7 +10,7 @@ import ( // UntarInPlace untars a .tar file using the same name as the file as the sub-folder name in the folder it was referenced in. // i.e., /opt/foo.tar will land in /opt/foo -// supports tar and tgz file formats +// supports tar and tgz file formats. func UntarInPlace(path string) error { folder := TrimExt(path) file, err := os.Open(path) @@ -26,7 +26,7 @@ func UntarInPlace(path string) error { // UnTar untars a tar or tgz file into the dest folder. // dest is the folder location // io.Reader is a reader that is tar (or compressed tar) format -// compressed is true if reader is a compressed format +// compressed is true if reader is a compressed format. func UnTar(dest string, r io.Reader, compressed bool) (err error) { if compressed { gzr, err := gzip.NewReader(r) diff --git a/internal/harness/harness.go b/internal/harness/harness.go index 446189f6..61439168 100644 --- a/internal/harness/harness.go +++ b/internal/harness/harness.go @@ -172,7 +172,7 @@ func (h *Harness) RunKIND() (*rest.Config, error) { } // initTempPath creates the temp folder if needed. -// various parts of system may need it, starting with kind, or working with tar test suites +// various parts of system may need it, starting with kind, or working with tar test suites. func (h *Harness) initTempPath() (err error) { if h.tempPath == "" { h.tempPath, err = os.MkdirTemp("", "kuttl") @@ -430,7 +430,7 @@ func (h *Harness) RunTests() { h.T.Log("run tests finished") } -// testPreProcessing provides preprocessing bring all tests suites local if there are any refers to URLs +// testPreProcessing provides preprocessing bring all tests suites local if there are any refers to URLs. func (h *Harness) testPreProcessing() []string { testDirs := []string{} // preprocessing step @@ -617,7 +617,7 @@ func (h *Harness) Stop() { } // wraps Test.Fatal in order to clean up harness -// fatal should NOT be used with a go routine, it is not thread safe +// fatal should NOT be used with a go routine, it is not thread safe. func (h *Harness) fatal(err error) { // clean up on fatal in setup if !h.stopping { @@ -644,7 +644,7 @@ func (h *Harness) Report() { } } -// NewSuiteReport creates and assigns a TestSuite to the TestSuites (then returns the suite), +// NewSuiteReport creates and assigns a TestSuite to the TestSuites (then returns the suite). func (h *Harness) NewSuiteReport(name string) *report.Testsuite { suite := report.NewSuite(name, h.TestSuite.ReportGranularity) h.report.AddTestSuite(suite) diff --git a/internal/harness/harness_integration_test.go b/internal/harness/harness_integration_test.go index 2b3aa228..6d9a661d 100644 --- a/internal/harness/harness_integration_test.go +++ b/internal/harness/harness_integration_test.go @@ -52,7 +52,7 @@ func TestHarnessRunIntegrationWithConfig(t *testing.T) { } } -// This test requires external KinD support to run thus is an integration test +// This test requires external KinD support to run thus is an integration test. func TestRunBackgroundCommands(t *testing.T) { h := Harness{ T: t, diff --git a/internal/http/client.go b/internal/http/client.go index cc77a679..2fce4e8c 100644 --- a/internal/http/client.go +++ b/internal/http/client.go @@ -16,7 +16,7 @@ import ( "github.com/kudobuilder/kuttl/internal/version" ) -// Client is client used to simplified http requests for tarballs +// Client is client used to simplified http requests for tarballs. type Client struct { client *http.Client UserAgent string @@ -35,7 +35,7 @@ func (c *Client) Get(url string) (*http.Response, error) { } // GetByteBuffer performs HTTP get, retrieves the contents and returns a bytes.Buffer of the entire contents -// this could be dangerous against an extremely large file +// this could be dangerous against an extremely large file. func (c *Client) GetByteBuffer(url string) (*bytes.Buffer, error) { buf := bytes.NewBuffer(nil) @@ -139,7 +139,7 @@ func (wc *writeCounter) Write(p []byte) (int, error) { return n, nil } -// PrintProgress prints the progress of a file write +// PrintProgress prints the progress of a file write. func (wc *writeCounter) PrintProgress() { // Clear the line by using a character return to go back to the start and remove // the remaining characters by filling it with spaces @@ -150,7 +150,7 @@ func (wc *writeCounter) PrintProgress() { fmt.Printf("\rDownloading (%s) %s complete", wc.Name, humanize.Bytes(wc.Total)) } -// NewClient creates HTTP client +// NewClient creates HTTP client. func NewClient() *Client { var client Client tr := &http.Transport{ diff --git a/internal/http/http.go b/internal/http/http.go index 2fe26736..d70c5ada 100644 --- a/internal/http/http.go +++ b/internal/http/http.go @@ -10,7 +10,7 @@ import ( "github.com/kudobuilder/kuttl/internal/kubernetes" ) -// IsURL returns true if string is an URL +// IsURL returns true if string is an URL. func IsURL(str string) bool { u, err := url.Parse(str) return err == nil && u.Scheme != "" && u.Host != "" @@ -35,7 +35,7 @@ func ToObjects(urlPath string) ([]client.Object, error) { return apply, nil } -// Read returns a buffer for the file at the url +// Read returns a buffer for the file at the url. func Read(urlPath string) (*bytes.Buffer, error) { c := NewClient() return c.GetByteBuffer(urlPath) diff --git a/internal/kubernetes/fake/dummy_test.go b/internal/kubernetes/fake/dummy_test.go index a7903dfa..54baefbe 100644 --- a/internal/kubernetes/fake/dummy_test.go +++ b/internal/kubernetes/fake/dummy_test.go @@ -3,7 +3,7 @@ package fake import "testing" -// TestDummy is a no-op test to satisfy coverage tools +// TestDummy is a no-op test to satisfy coverage tools. func TestDummy(_ *testing.T) { // This test exists only to ensure the package is recognized by go test // and to avoid "go: no such tool 'covdata'" warnings diff --git a/internal/kubernetes/retry_client_integration_test.go b/internal/kubernetes/retry_client_integration_test.go index 0e069ef1..c9b131e8 100644 --- a/internal/kubernetes/retry_client_integration_test.go +++ b/internal/kubernetes/retry_client_integration_test.go @@ -36,7 +36,7 @@ func TestMain(m *testing.M) { func TestCreateOrUpdate(t *testing.T) { // Run the test a bunch of times to try to trigger a conflict and ensure that it handles conflicts properly. - for i := 0; i < 10; i++ { + for i := range 10 { namespaceName := fmt.Sprintf("default-%d", i) namespaceObj := NewResource("v1", "Namespace", namespaceName, "default") diff --git a/internal/kubernetes/serialization.go b/internal/kubernetes/serialization.go index e3b96dac..09146222 100644 --- a/internal/kubernetes/serialization.go +++ b/internal/kubernetes/serialization.go @@ -77,7 +77,7 @@ func countLines(k string, v interface{}) (int, error) { return strings.Count(buf.String(), "\n"), nil } -// PrettyDiff creates a unified diff highlighting the differences between two Kubernetes resources +// PrettyDiff creates a unified diff highlighting the differences between two Kubernetes resources. func PrettyDiff(expected *unstructured.Unstructured, actual *unstructured.Unstructured) (string, error) { actualPruned := pruneLargeAdditions(expected, actual) @@ -199,7 +199,7 @@ func LoadYAMLFromFile(path string) ([]client.Object, error) { return LoadYAML(path, opened) } -// LoadYAML loads all objects from a reader +// LoadYAML loads all objects from a reader. func LoadYAML(path string, r io.Reader) ([]client.Object, error) { yamlReader := yaml.NewYAMLReader(bufio.NewReader(r)) diff --git a/internal/kubernetes/unstructured.go b/internal/kubernetes/unstructured.go index 6adbd6ad..69324671 100644 --- a/internal/kubernetes/unstructured.go +++ b/internal/kubernetes/unstructured.go @@ -31,7 +31,7 @@ func NewResource(apiVersion, kind, name, namespace string) *unstructured.Unstruc } } -// NewClusterRoleBinding Create a clusterrolebinding for the serviceAccount passed +// NewClusterRoleBinding Create a clusterrolebinding for the serviceAccount passed. func NewClusterRoleBinding(apiVersion, kind, name, namespace string, serviceAccount string, roleName string) runtime.Object { sa := &rbacv1.ClusterRoleBinding{ ObjectMeta: metav1.ObjectMeta{ diff --git a/internal/kuttlctl/cmd/assert.go b/internal/kuttlctl/cmd/assert.go index 0eea79d2..32609ac0 100644 --- a/internal/kuttlctl/cmd/assert.go +++ b/internal/kuttlctl/cmd/assert.go @@ -14,7 +14,7 @@ var ( kubectl kuttl assert ` ) -// newAssertCmd returns a new initialized instance of the assert sub command +// newAssertCmd returns a new initialized instance of the assert sub command. func newAssertCmd() *cobra.Command { timeout := 5 namespace := "default" diff --git a/internal/kuttlctl/cmd/errors.go b/internal/kuttlctl/cmd/errors.go index dda35722..27ee9872 100644 --- a/internal/kuttlctl/cmd/errors.go +++ b/internal/kuttlctl/cmd/errors.go @@ -13,7 +13,7 @@ var ( kubectl kuttl errors ...` ) -// newErrorsCmd returns a new initialized instance of the errors sub command +// newErrorsCmd returns a new initialized instance of the errors sub command. func newErrorsCmd() *cobra.Command { timeout := 5 namespace := "default" diff --git a/internal/kuttlctl/cmd/root.go b/internal/kuttlctl/cmd/root.go index 53e51e8a..ec4e3c75 100644 --- a/internal/kuttlctl/cmd/root.go +++ b/internal/kuttlctl/cmd/root.go @@ -7,7 +7,7 @@ import ( "github.com/kudobuilder/kuttl/internal/version" ) -// NewKuttlCmd creates a new root command for kuttlctl +// NewKuttlCmd creates a new root command for kuttlctl. func NewKuttlCmd() *cobra.Command { cmd := &cobra.Command{ Use: "kubectl-kuttl", diff --git a/internal/kuttlctl/cmd/test.go b/internal/kuttlctl/cmd/test.go index 75ab539f..e2d6d5cd 100644 --- a/internal/kuttlctl/cmd/test.go +++ b/internal/kuttlctl/cmd/test.go @@ -43,7 +43,7 @@ var ( ` ) -// newTestCmd creates the test command for the CLI +// newTestCmd creates the test command for the CLI. func newTestCmd() *cobra.Command { //nolint:gocyclo configPath := "" crdDir := "" diff --git a/internal/kuttlctl/cmd/version.go b/internal/kuttlctl/cmd/version.go index 28d03b36..30fd9cbe 100644 --- a/internal/kuttlctl/cmd/version.go +++ b/internal/kuttlctl/cmd/version.go @@ -13,7 +13,7 @@ var ( kubectl kuttl version` ) -// newVersionCmd returns a new initialized instance of the version sub command +// newVersionCmd returns a new initialized instance of the version sub command. func newVersionCmd() *cobra.Command { versionCmd := &cobra.Command{ Use: "version", @@ -26,7 +26,7 @@ func newVersionCmd() *cobra.Command { return versionCmd } -// VersionCmd performs the version sub command +// VersionCmd performs the version sub command. func VersionCmd(_ *cobra.Command, _ []string) error { kuttlVersion := version.Get() fmt.Printf("KUTTL Version: %s\n", fmt.Sprintf("%#v", kuttlVersion)) diff --git a/internal/report/report.go b/internal/report/report.go index 19373286..b1789a3d 100644 --- a/internal/report/report.go +++ b/internal/report/report.go @@ -130,25 +130,25 @@ type TestReporter interface { Done() } -// NewSuiteCollection returns the address of a newly created TestSuites +// NewSuiteCollection returns the address of a newly created TestSuites. func NewSuiteCollection(name string) *Testsuites { start := time.Now() return &Testsuites{XMLName: xml.Name{Local: "testsuites"}, Name: name, start: start} } -// NewSuite returns the address of a newly created TestSuite +// NewSuite returns the address of a newly created TestSuite. func NewSuite(name string, reportGranularity string) *Testsuite { start := time.Now() return &Testsuite{Name: name, Timestamp: start, reportGranularity: reportGranularity} } -// NewCase returns the address of a newly create Testcase +// NewCase returns the address of a newly create Testcase. func NewCase(name string) *Testcase { start := time.Now() return &Testcase{Name: name, Timestamp: start} } -// NewFailure returns the address of a newly created Failure +// NewFailure returns the address of a newly created Failure. func NewFailure(msg string, errs []error) *Failure { f := &Failure{Message: msg} @@ -162,7 +162,7 @@ func NewFailure(msg string, errs []error) *Failure { return f } -// AddTestcase adds a testcase to a suite, providing stats and calculations to both +// AddTestcase adds a testcase to a suite, providing stats and calculations to both. func (ts *Testsuite) AddTestcase(testcase *Testcase) { // this is needed to calc elapse time of testsuite in a async work testcase.end = time.Now() @@ -182,7 +182,7 @@ func (ts *Testsuite) AddTestcase(testcase *Testcase) { } } -// AddProperty adds a property to a testsuite +// AddProperty adds a property to a testsuite. func (ts *Testsuite) AddProperty(property Property) { if ts.Properties == nil { ts.Properties = &Properties{Property: []Property{property}} @@ -299,7 +299,7 @@ func (r *testReporter) Done() { var _ TestReporter = (*testReporter)(nil) var _ StepReporter = (*stepReport)(nil) -// AddTestSuite is a convenience method to add a testsuite to the collection in testsuites +// AddTestSuite is a convenience method to add a testsuite to the collection in testsuites. func (ts *Testsuites) AddTestSuite(testsuite *Testsuite) { // testsuite is added prior to stat availability, stat management in the close of the testsuites ts.lock.Lock() @@ -311,7 +311,7 @@ func (ts *Testsuites) AddTestSuite(testsuite *Testsuite) { }) } -// AddProperty adds a property to a testsuites +// AddProperty adds a property to a testsuites. func (ts *Testsuites) AddProperty(property Property) { if ts.Properties == nil { ts.Properties = &Properties{Property: []Property{property}} @@ -324,7 +324,7 @@ func (ts *Testsuites) AddProperty(property Property) { ts.Properties.Property = append(ts.Properties.Property, property) } -// Close closes the report and does all end stat calculations +// Close closes the report and does all end stat calculations. func (ts *Testsuites) Close() { elapsed := time.Since(ts.start) ts.Time = fmt.Sprintf("%.3f", elapsed.Seconds()) @@ -340,7 +340,7 @@ func (ts *Testsuites) Close() { // latestEnd provides the time of the latest end out of the collection of testcases -// Report prints a report for TestSuites to the directory. ftype == json | xml +// Report prints a report for TestSuites to the directory. ftype == json | xml. func (ts *Testsuites) Report(dir, name string, ftype Type) error { ts.Close() @@ -374,7 +374,7 @@ func ensureDir(dir string) error { return err } -// SetFailure adds a failure to the TestSuites collection for startup failures in the test harness +// SetFailure adds a failure to the TestSuites collection for startup failures in the test harness. func (ts *Testsuites) SetFailure(message string) { ts.Failure = &Failure{ Message: message, diff --git a/internal/step/step.go b/internal/step/step.go index bdb03fb5..2ecac7c4 100644 --- a/internal/step/step.go +++ b/internal/step/step.go @@ -704,7 +704,7 @@ func (s *Step) Setup(caseLogger testutils.Logger, defaultClientFunc func(forceNe } } -// ObjectsFromPath returns an array of runtime.Objects for files / urls provided +// ObjectsFromPath returns an array of runtime.Objects for files / urls provided. func ObjectsFromPath(path, dir string) ([]client.Object, error) { if http.IsURL(path) { apply, err := http.ToObjects(path) @@ -727,7 +727,7 @@ func ObjectsFromPath(path, dir string) ([]client.Object, error) { return apply, nil } -// cleanPath returns either the abs path or the joined path +// cleanPath returns either the abs path or the joined path. func cleanPath(path, dir string) string { if filepath.IsAbs(path) { return path diff --git a/internal/testcase/case_test.go b/internal/testcase/case_test.go index b38e053a..eeb14a06 100644 --- a/internal/testcase/case_test.go +++ b/internal/testcase/case_test.go @@ -552,6 +552,7 @@ func TestCase_createNamespace(t *testing.T) { // Optionally it also refuses Get operations. type noPermClient struct { client.Client + forbidGet bool t *testing.T } diff --git a/internal/testcase/client.go b/internal/testcase/client.go index f518c508..932a25e9 100644 --- a/internal/testcase/client.go +++ b/internal/testcase/client.go @@ -10,6 +10,7 @@ import ( type clientWithKubeConfig struct { client.Client + kubeConfigPath string logger testutils.Logger } diff --git a/internal/utils/commands.go b/internal/utils/commands.go index d6420921..3001c6cf 100644 --- a/internal/utils/commands.go +++ b/internal/utils/commands.go @@ -71,7 +71,7 @@ func GetArgs(ctx context.Context, cmd harness.Command, namespace string, envMap // RunCommand runs a command with args. // args gets split on spaces (respecting quoted strings). -// if the command is run in the background a reference to the process is returned for later cleanup +// if the command is run in the background a reference to the process is returned for later cleanup. func RunCommand(ctx context.Context, namespace string, cmd harness.Command, cwd string, stdout io.Writer, stderr io.Writer, logger Logger, timeout int, kubeconfigOverride string) (*exec.Cmd, error) { actualDir, err := os.Getwd() if err != nil { @@ -180,14 +180,14 @@ func convertAssertCommand(assertCommands []harness.TestAssertCommand, timeout in return commands } -// RunAssertCommands runs a set of commands specified as TestAssertCommand +// RunAssertCommands runs a set of commands specified as TestAssertCommand. func RunAssertCommands(ctx context.Context, logger Logger, namespace string, commands []harness.TestAssertCommand, workdir string, timeout int, kubeconfigOverride string) ([]*exec.Cmd, error) { return RunCommands(ctx, logger, namespace, convertAssertCommand(commands, timeout), workdir, timeout, kubeconfigOverride) } // RunCommands runs a set of commands, returning any errors. // If any (non-background) command fails, the following commands are skipped -// commands running in the background are returned +// commands running in the background are returned. func RunCommands(ctx context.Context, logger Logger, namespace string, commands []harness.Command, workdir string, timeout int, kubeconfigOverride string) ([]*exec.Cmd, error) { bgs := []*exec.Cmd{} diff --git a/internal/utils/docker.go b/internal/utils/docker.go index 40e30f40..cafaac37 100644 --- a/internal/utils/docker.go +++ b/internal/utils/docker.go @@ -8,6 +8,6 @@ import ( // DockerClient is a wrapper interface for the Docker library to support unit testing. type DockerClient interface { - VolumeCreate(context.Context, client.VolumeCreateOptions) (client.VolumeCreateResult, error) - ImageSave(context.Context, []string, ...client.ImageSaveOption) (client.ImageSaveResult, error) + VolumeCreate(ctx context.Context, options client.VolumeCreateOptions) (client.VolumeCreateResult, error) + ImageSave(ctx context.Context, imageIDs []string, opts ...client.ImageSaveOption) (client.ImageSaveResult, error) } diff --git a/internal/utils/events/dummy_test.go b/internal/utils/events/dummy_test.go index 9f62b9fb..d34c00f1 100644 --- a/internal/utils/events/dummy_test.go +++ b/internal/utils/events/dummy_test.go @@ -3,7 +3,7 @@ package events import "testing" -// TestDummy is a no-op test to satisfy coverage tools +// TestDummy is a no-op test to satisfy coverage tools. func TestDummy(_ *testing.T) { // This test exists only to ensure the package is recognized by go test // and to avoid "go: no such tool 'covdata'" warnings diff --git a/internal/utils/files/files_test.go b/internal/utils/files/files_test.go index d69d72ae..1cc31e8c 100644 --- a/internal/utils/files/files_test.go +++ b/internal/utils/files/files_test.go @@ -11,7 +11,7 @@ import ( testutils "github.com/kudobuilder/kuttl/internal/utils" ) -// mockLogger is a simple logger that captures log messages for testing +// mockLogger is a simple logger that captures log messages for testing. type mockLogger struct { messages []string } diff --git a/internal/utils/logger.go b/internal/utils/logger.go index 78f7f1f1..11719db0 100644 --- a/internal/utils/logger.go +++ b/internal/utils/logger.go @@ -11,7 +11,7 @@ import ( type Logger interface { Log(args ...interface{}) Logf(format string, args ...interface{}) - WithPrefix(string) Logger + WithPrefix(prefix string) Logger Write(p []byte) (n int, err error) Flush() } diff --git a/internal/utils/subset.go b/internal/utils/subset.go index 7968aa5e..476684f1 100644 --- a/internal/utils/subset.go +++ b/internal/utils/subset.go @@ -11,7 +11,7 @@ type SubsetError struct { message string } -// AppendPath appends key to the existing struct path. For example, in struct member `a.Key1.Key2`, the path would be ["Key1", "Key2"] +// AppendPath appends key to the existing struct path. For example, in struct member `a.Key1.Key2`, the path would be ["Key1", "Key2"]. func (e *SubsetError) AppendPath(key string) { if e.path == nil { e.path = []string{} @@ -55,7 +55,7 @@ func IsSubset(expected, actual interface{}) error { } } - for i := 0; i < reflect.ValueOf(expected).Len(); i++ { + for i := range reflect.ValueOf(expected).Len() { if err := IsSubset(reflect.ValueOf(expected).Index(i).Interface(), reflect.ValueOf(actual).Index(i).Interface()); err != nil { return err } diff --git a/internal/version/base.go b/internal/version/base.go index 3a5ec763..5075d8b0 100644 --- a/internal/version/base.go +++ b/internal/version/base.go @@ -16,7 +16,7 @@ package version var ( // semantic version, derived by build scripts (see // https://github.com/kubernetes/community/blob/master/contributors/design-proposals/release/versioning.md - // for a detailed discussion of this field) + // for a detailed discussion of this field). gitVersion = "v0.0.0-main+$Format:%h$" gitCommit = "$Format:%H$" // sha1 from git, output of $(git rev-parse HEAD) diff --git a/internal/version/version.go b/internal/version/version.go index bb0ae630..dae9ab02 100644 --- a/internal/version/version.go +++ b/internal/version/version.go @@ -52,7 +52,7 @@ func Get() Info { } } -// Version is an extension of semver.Version +// Version is an extension of semver.Version. type Version struct { *semver.Version } @@ -70,7 +70,7 @@ func (v *Version) CompareMajorMinor(o *Version) int { return 0 } -// compares v1 against v2 resulting in -1, 0, 1 for less than, equal, greater than +// compares v1 against v2 resulting in -1, 0, 1 for less than, equal, greater than. func compareSegment(v1, v2 uint64) int { if v1 < v2 { return -1 @@ -82,7 +82,7 @@ func compareSegment(v1, v2 uint64) int { return 0 } -// New provides an instance of Version from a semver string +// New provides an instance of Version from a semver string. func New(v string) (*Version, error) { ver, err := semver.NewVersion(v) if err != nil { @@ -92,12 +92,12 @@ func New(v string) (*Version, error) { } // FromGithubVersion provides a version parsed from github semver which starts with "v". -// v1.5.2 provides a sem version of 1.5.2 +// v1.5.2 provides a sem version of 1.5.2. func FromGithubVersion(v string) (*Version, error) { return New(Clean(v)) } -// FromSemVer converts a semver.Version to our Version +// FromSemVer converts a semver.Version to our Version. func FromSemVer(v *semver.Version) *Version { return &Version{v} } @@ -107,7 +107,7 @@ func MustParse(v string) *Version { return FromSemVer(semver.MustParse(v)) } -// Clean returns version without a prefixed v if it exists +// Clean returns version without a prefixed v if it exists. func Clean(ver string) string { if strings.HasPrefix(ver, "v") { return ver[1:] diff --git a/pkg/apis/dummy_test.go b/pkg/apis/dummy_test.go index 181c297f..054ca882 100644 --- a/pkg/apis/dummy_test.go +++ b/pkg/apis/dummy_test.go @@ -2,7 +2,7 @@ package apis import "testing" -// TestDummy is a no-op test to satisfy coverage tools +// TestDummy is a no-op test to satisfy coverage tools. func TestDummy(_ *testing.T) { // This test exists only to ensure the package is recognized by go test // and to avoid "go: no such tool 'covdata'" warnings diff --git a/pkg/apis/testharness/v1beta1/collector.go b/pkg/apis/testharness/v1beta1/collector.go index 69d8954a..87c6d047 100644 --- a/pkg/apis/testharness/v1beta1/collector.go +++ b/pkg/apis/testharness/v1beta1/collector.go @@ -13,7 +13,7 @@ const ( ) // validate checks user input and updates type if not provided. -// It is expected to be called prior to any other call +// It is expected to be called prior to any other call. func (tc *TestCollector) validate() error { cleanType(tc) switch tc.Type { @@ -55,7 +55,7 @@ func validateCmd(tc *TestCollector) error { return nil } -// determines and cleans collector type +// determines and cleans collector type. func cleanType(tc *TestCollector) { // intuit pod or command or invalid if tc.Type == "" { @@ -69,7 +69,7 @@ func cleanType(tc *TestCollector) { tc.Type = strings.ToLower(tc.Type) } -// Command provides the command to exec to perform the collection +// Command provides the command to exec to perform the collection. func (tc *TestCollector) Command() *Command { err := tc.validate() if err != nil { @@ -139,7 +139,7 @@ func podCommand(tc *TestCollector) *Command { } } -// String provides defaults of the type of collector +// String provides defaults of the type of collector. func (tc *TestCollector) String() string { err := tc.validate() if err != nil { diff --git a/pkg/apis/testharness/v1beta1/test_types.go b/pkg/apis/testharness/v1beta1/test_types.go index 2a246481..cd092394 100644 --- a/pkg/apis/testharness/v1beta1/test_types.go +++ b/pkg/apis/testharness/v1beta1/test_types.go @@ -109,7 +109,7 @@ type TestSuite struct { // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// TestStep settings to apply to a test step.go +// TestStep contains settings to apply to a test step. type TestStep struct { // The type meta object, should always be a GVK of kuttl.dev/v1beta1/TestStep or kuttl.dev/v1beta1/TestStep. metav1.TypeMeta `json:",inline"` @@ -158,6 +158,7 @@ type TestAssert struct { metav1.TypeMeta `json:",inline"` // Override the default metadata. Set labels or override the test step name. metav1.ObjectMeta `json:"metadata,omitempty"` + // Override the default timeout of 30 seconds (in seconds). Timeout int `json:"timeout"` // Collectors is a set of pod log collectors fired on an assert failure @@ -171,7 +172,7 @@ type TestAssert struct { AssertAll []*Assertion `json:"assertAll,omitempty"` } -// TestAssertCommand an assertion based on the result of the execution of a command +// TestAssertCommand an assertion based on the result of the execution of a command. type TestAssertCommand struct { // The command and argument to run as a string. Command string `json:"command"` @@ -189,6 +190,7 @@ type TestAssertCommand struct { // objects by label. type ObjectReference struct { corev1.ObjectReference `json:",inline"` + // Labels to match on. Labels map[string]string `json:"labels"` }