From 1ece5924fbf4c72e90fd73a99fe96eef8535a8c2 Mon Sep 17 00:00:00 2001 From: Dave Henderson Date: Sat, 21 Oct 2023 17:15:58 -0400 Subject: [PATCH] A bunch of linting and refactorings Signed-off-by: Dave Henderson --- .github/workflows/build.yml | 2 +- .golangci.yml | 23 +- LICENSE | 2 +- README.md | 2 +- coll/coll_test.go | 24 ++- coll/jsonpath_test.go | 6 +- config.go | 2 +- context.go | 6 +- conv/conv.go | 4 - conv/conv_test.go | 19 +- crypto/ecdsa.go | 22 +- data/data_test.go | 14 +- data/datasource_aws_sm.go | 2 +- data/datasource_aws_sm_test.go | 4 +- data/datasource_awssmp.go | 1 - data/datasource_blob_test.go | 14 +- data/datasource_env.go | 1 + data/datasource_git.go | 5 +- data/datasource_git_test.go | 198 ++++++++++++------ data/datasource_http_test.go | 1 - data/datasource_test.go | 84 +++++--- funcs.go | 6 +- funcs/crypto.go | 11 +- funcs/crypto_test.go | 1 - funcs/data.go | 6 +- funcs/file_test.go | 4 +- funcs/gcp.go | 16 +- funcs/math_test.go | 1 + funcs/net.go | 2 - funcs/net_test.go | 1 + funcs/random_test.go | 4 +- gcp/meta.go | 12 +- gomplate.go | 2 +- gomplate_test.go | 1 - internal/cmd/main.go | 3 +- internal/config/configfile.go | 8 +- internal/config/configfile_test.go | 11 +- internal/config/types_test.go | 6 +- internal/iohelpers/writers_test.go | 4 +- internal/tests/integration/basic_test.go | 14 +- internal/tests/integration/config_test.go | 4 +- .../tests/integration/datasources_env_test.go | 1 - .../integration/datasources_vault_test.go | 6 +- internal/tests/integration/file_test.go | 2 +- internal/tests/integration/inputdir_test.go | 46 ++-- .../tests/integration/integration_test.go | 10 +- internal/tests/integration/plugins_test.go | 14 +- .../tests/integration/plugins_windows_test.go | 8 +- internal/tests/integration/tmpl_test.go | 2 +- libkv/consul.go | 1 - net/net_test.go | 1 + plugins.go | 1 - random/random.go | 2 +- regexp/regexp_test.go | 1 + render.go | 23 +- template.go | 7 +- template_test.go | 16 +- vault/testutils.go | 3 +- version/gen/vgen.go | 11 +- version/gen/vgen_test.go | 3 +- 60 files changed, 404 insertions(+), 307 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 879b17253..daa98bdbc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -47,7 +47,7 @@ jobs: - run: pwd - uses: actions/setup-go@v4 with: - go-version: '1.20' + go-version: '1.21' - run: | git config --global user.email "bogus@example.com" git config --global user.name "Someone" diff --git a/.golangci.yml b/.golangci.yml index 260ffec18..2ddcc5c76 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,8 +1,7 @@ linters-settings: govet: check-shadowing: true - enable: - - fieldalignment + enable-all: true golint: min-confidence: 0 gocyclo: @@ -11,7 +10,7 @@ linters-settings: threshold: 100 goconst: min-len: 2 - min-occurrences: 6 + min-occurrences: 5 ignore-tests: true lll: line-length: 140 @@ -28,7 +27,7 @@ linters: - bodyclose # - dogsled # - dupl - # - errcheck + - errcheck # - exhaustive - exportloopref # - funlen @@ -41,7 +40,7 @@ linters: # - gocyclo # - godox - gofmt - # - gofumpt + - gofumpt - goheader - goimports # - gomnd @@ -56,8 +55,8 @@ linters: - nakedret - nestif # - nlreturn - # - noctx - # - nolintlint + - noctx + - nolintlint - prealloc - revive - rowserrcheck @@ -66,11 +65,17 @@ linters: - stylecheck - typecheck - unconvert - # - unparam + - unparam - unused - # - whitespace + - whitespace # - wsl +issues: + exclude-rules: + - path: _test\.go + linters: + - errcheck + run: concurrency: 4 timeout: 5m diff --git a/LICENSE b/LICENSE index 008edbc3b..eec4a3661 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2016-2018 Dave Henderson +Copyright (c) 2016-2023 Dave Henderson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal diff --git a/README.md b/README.md index e9c2b63e0..17d441496 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ _Please report any bugs found in the [issue tracker](https://github.com/hairyhen [The MIT License](http://opensource.org/licenses/MIT) -Copyright (c) 2016-2022 Dave Henderson +Copyright (c) 2016-2023 Dave Henderson [gh-actions-image]: https://github.com/hairyhenderson/gomplate/workflows/Build/badge.svg?branch=main [gh-actions-url]: https://github.com/hairyhenderson/gomplate/actions?workflow=Build&branch=main diff --git a/coll/coll_test.go b/coll/coll_test.go index 31ad1d91c..e1f1de4af 100644 --- a/coll/coll_test.go +++ b/coll/coll_test.go @@ -241,7 +241,8 @@ func TestMerge(t *testing.T) { assert.EqualValues(t, expected, out) dst = map[string]interface{}{"a": true, "c": 5} - src = map[string]interface{}{"a": false, + src = map[string]interface{}{ + "a": false, "b": map[string]interface{}{ "ca": "foo", }, @@ -261,7 +262,8 @@ func TestMerge(t *testing.T) { "ca": "foo", "cb": "bar", }, - "c": 5} + "c": 5, + } src = map[string]interface{}{ "a": false, "b": map[string]interface{}{ @@ -478,24 +480,28 @@ func TestFlatten(t *testing.T) { {in: []int{1, 2, 3}, expected: []interface{}{1, 2, 3}}, {in: [3]int{1, 2, 3}, expected: []interface{}{1, 2, 3}}, {in: []interface{}{[]string{}, []int{1, 2}, 3}, expected: []interface{}{[]string{}, []int{1, 2}, 3}}, - {in: []interface{}{[]string{"one"}, [][]int{{1, 2}}, 3}, + { + in: []interface{}{[]string{"one"}, [][]int{{1, 2}}, 3}, expected: []interface{}{[]string{"one"}, [][]int{{1, 2}}, 3}, }, {depth: 1, in: []int{1, 2, 3}, expected: []interface{}{1, 2, 3}}, {depth: 1, in: [3]int{1, 2, 3}, expected: []interface{}{1, 2, 3}}, {depth: 1, in: []interface{}{[]string{}, []int{1, 2}, 3}, expected: []interface{}{1, 2, 3}}, - {depth: 1, + { + depth: 1, in: []interface{}{[]string{"one"}, [][]int{{1, 2}}, 3}, expected: []interface{}{"one", []int{1, 2}, 3}, }, {depth: 2, in: []int{1, 2, 3}, expected: []interface{}{1, 2, 3}}, {depth: 2, in: [3]int{1, 2, 3}, expected: []interface{}{1, 2, 3}}, {depth: 2, in: []interface{}{[]string{}, []int{1, 2}, 3}, expected: []interface{}{1, 2, 3}}, - {depth: 2, + { + depth: 2, in: []interface{}{[]string{"one"}, [][]int{{1, 2}}, 3}, expected: []interface{}{"one", 1, 2, 3}, }, - {depth: 2, + { + depth: 2, in: []interface{}{ []string{"one"}, []interface{}{ @@ -512,11 +518,13 @@ func TestFlatten(t *testing.T) { {depth: -1, in: []int{1, 2, 3}, expected: []interface{}{1, 2, 3}}, {depth: -1, in: [3]int{1, 2, 3}, expected: []interface{}{1, 2, 3}}, {depth: -1, in: []interface{}{[]string{}, []int{1, 2}, 3}, expected: []interface{}{1, 2, 3}}, - {depth: -1, + { + depth: -1, in: []interface{}{[]string{"one"}, [][]int{{1, 2}}, 3}, expected: []interface{}{"one", 1, 2, 3}, }, - {depth: -1, + { + depth: -1, in: []interface{}{ []string{"one"}, []interface{}{ diff --git a/coll/jsonpath_test.go b/coll/jsonpath_test.go index c697e4de8..ab464240a 100644 --- a/coll/jsonpath_test.go +++ b/coll/jsonpath_test.go @@ -7,8 +7,10 @@ import ( "github.com/stretchr/testify/require" ) -type m = map[string]interface{} -type ar = []interface{} +type ( + m = map[string]interface{} + ar = []interface{} +) func TestJSONPath(t *testing.T) { in := m{ diff --git a/config.go b/config.go index 95d43f71b..52a5800cf 100644 --- a/config.go +++ b/config.go @@ -58,7 +58,7 @@ func (o *Config) defaults() *Config { return o } -// nolint: gocyclo +//nolint:gocyclo func (o *Config) String() string { o.defaults() diff --git a/context.go b/context.go index 110f2e138..dd8557de4 100644 --- a/context.go +++ b/context.go @@ -22,9 +22,9 @@ func (c *tmplctx) Env() map[string]string { } // createTmplContext reads the datasources for the given aliases -func createTmplContext(_ context.Context, aliases []string, - //nolint:staticcheck - d *data.Data) (interface{}, error) { +// +//nolint:staticcheck +func createTmplContext(_ context.Context, aliases []string, d *data.Data) (interface{}, error) { var err error tctx := &tmplctx{} for _, a := range aliases { diff --git a/conv/conv.go b/conv/conv.go index 4ea066952..62990e39d 100644 --- a/conv/conv.go +++ b/conv/conv.go @@ -158,28 +158,24 @@ func ToStrings(in ...interface{}) []string { // MustParseInt - wrapper for strconv.ParseInt that returns 0 in the case of error func MustParseInt(s string, base, bitSize int) int64 { - // nolint: gosec i, _ := strconv.ParseInt(s, base, bitSize) return i } // MustParseFloat - wrapper for strconv.ParseFloat that returns 0 in the case of error func MustParseFloat(s string, bitSize int) float64 { - // nolint: gosec i, _ := strconv.ParseFloat(s, bitSize) return i } // MustParseUint - wrapper for strconv.ParseUint that returns 0 in the case of error func MustParseUint(s string, base, bitSize int) uint64 { - // nolint: gosec i, _ := strconv.ParseUint(s, base, bitSize) return i } // MustAtoi - wrapper for strconv.Atoi that returns 0 in the case of error func MustAtoi(s string) int { - // nolint: gosec i, _ := strconv.Atoi(s) return i } diff --git a/conv/conv_test.go b/conv/conv_test.go index 686667bb4..f324fdc10 100644 --- a/conv/conv_test.go +++ b/conv/conv_test.go @@ -67,7 +67,6 @@ func TestJoin(t *testing.T) { } func TestHas(t *testing.T) { - in := map[string]interface{}{ "foo": "bar", "baz": map[string]interface{}{ @@ -315,25 +314,31 @@ func TestDict(t *testing.T) { {expected: map[string]interface{}{}}, { args: []interface{}{}, - expected: map[string]interface{}{}}, + expected: map[string]interface{}{}, + }, { args: []interface{}{"foo"}, - expected: map[string]interface{}{"foo": ""}}, + expected: map[string]interface{}{"foo": ""}, + }, { args: []interface{}{42}, - expected: map[string]interface{}{"42": ""}}, + expected: map[string]interface{}{"42": ""}, + }, { args: []interface{}{"foo", nil}, - expected: map[string]interface{}{"foo": nil}}, + expected: map[string]interface{}{"foo": nil}, + }, { args: []interface{}{"foo", "bar"}, - expected: map[string]interface{}{"foo": "bar"}}, + expected: map[string]interface{}{"foo": "bar"}, + }, { args: []interface{}{"foo", "bar", "baz", true}, expected: map[string]interface{}{ "foo": "bar", "baz": true, - }}, + }, + }, } for _, d := range testdata { diff --git a/crypto/ecdsa.go b/crypto/ecdsa.go index 6f3773908..02212b20c 100644 --- a/crypto/ecdsa.go +++ b/crypto/ecdsa.go @@ -10,15 +10,21 @@ import ( "fmt" ) -var ( - // Curves is a map of curve names to curves - Curves = map[string]elliptic.Curve{ - "P224": elliptic.P224(), - "P256": elliptic.P256(), - "P384": elliptic.P384(), - "P521": elliptic.P521(), +// Curves - +func Curves(c string) (elliptic.Curve, bool) { + switch c { + case "P224": + return elliptic.P224(), true + case "P256": + return elliptic.P256(), true + case "P384": + return elliptic.P384(), true + case "P521": + return elliptic.P521(), true + default: + return nil, false } -) +} // ECDSAGenerateKey - func ECDSAGenerateKey(curve elliptic.Curve) ([]byte, error) { diff --git a/data/data_test.go b/data/data_test.go index 324a36007..e4f0f555c 100644 --- a/data/data_test.go +++ b/data/data_test.go @@ -2,6 +2,7 @@ package data import ( "fmt" + "os" "testing" "time" @@ -10,8 +11,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "os" - "gotest.tools/v3/fs" ) @@ -65,12 +64,14 @@ escaped: "\"\/\\\b\f\n\r\t\u221e" } func TestUnmarshalArray(t *testing.T) { - expected := []interface{}{"foo", "bar", + expected := []interface{}{ + "foo", "bar", map[string]interface{}{ "baz": map[string]interface{}{"qux": true}, "quux": map[string]interface{}{"42": 18}, "corge": map[string]interface{}{"false": "blah"}, - }} + }, + } test := func(actual []interface{}, err error) { require.NoError(t, err) @@ -167,15 +168,13 @@ func TestToJSONBytes(t *testing.T) { assert.Error(t, err) } -type badObject struct { -} +type badObject struct{} func (b *badObject) CodecEncodeSelf(_ *codec.Encoder) { panic("boom") } func (b *badObject) CodecDecodeSelf(_ *codec.Decoder) { - } func TestToJSON(t *testing.T) { @@ -505,7 +504,6 @@ true = true assert.Equal(t, expected, out) } -//nolint:gosec func TestDecryptEJSON(t *testing.T) { privateKey := "e282d979654f88267f7e6c2d8268f1f4314b8673579205ed0029b76de9c8223f" publicKey := "6e05ec625bcdca34864181cc43e6fcc20a57732a453bc2f4a2e117ffdf1a6762" diff --git a/data/datasource_aws_sm.go b/data/datasource_aws_sm.go index 5edacfd80..aa42fdf90 100644 --- a/data/datasource_aws_sm.go +++ b/data/datasource_aws_sm.go @@ -56,7 +56,7 @@ func parseDatasourceURLArgs(sourceURL *url.URL, args ...string) (params map[stri return params, p, nil } -func readAWSSecretsManager(ctx context.Context, source *Source, args ...string) (output []byte, err error) { +func readAWSSecretsManager(ctx context.Context, source *Source, args ...string) ([]byte, error) { if source.awsSecretsManager == nil { source.awsSecretsManager = secretsmanager.New(gaws.SDKSession()) } diff --git a/data/datasource_aws_sm_test.go b/data/datasource_aws_sm_test.go index 17f61603b..e6e2cef39 100644 --- a/data/datasource_aws_sm_test.go +++ b/data/datasource_aws_sm_test.go @@ -153,7 +153,7 @@ func TestAWSSecretsManager_ReadSecret(t *testing.T) { }, }) - output, err := readAWSSecretsManagerParam(context.Background(), s, "/foo/bar") + output, err := readAWSSecretsManager(context.Background(), s, "/bar") assert.True(t, calledOk) require.NoError(t, err) assert.Equal(t, []byte("blub"), output) @@ -170,7 +170,7 @@ func TestAWSSecretsManager_ReadSecretBinary(t *testing.T) { }, }) - output, err := readAWSSecretsManagerParam(context.Background(), s, "/foo/bar") + output, err := readAWSSecretsManager(context.Background(), s, "/bar") assert.True(t, calledOk) require.NoError(t, err) assert.Equal(t, []byte("supersecret"), output) diff --git a/data/datasource_awssmp.go b/data/datasource_awssmp.go index fefe46b8a..749791299 100644 --- a/data/datasource_awssmp.go +++ b/data/datasource_awssmp.go @@ -46,7 +46,6 @@ func readAWSSMPParam(ctx context.Context, source *Source, paramPath string) ([]b } response, err := source.asmpg.GetParameterWithContext(ctx, input) - if err != nil { return nil, fmt.Errorf("error reading aws+smp from AWS using GetParameter with input %v: %w", input, err) } diff --git a/data/datasource_blob_test.go b/data/datasource_blob_test.go index b3e40e3e1..c79780d0b 100644 --- a/data/datasource_blob_test.go +++ b/data/datasource_blob_test.go @@ -23,32 +23,32 @@ func setupTestBucket(t *testing.T) (*httptest.Server, *url.URL) { err := backend.CreateBucket("mybucket") require.NoError(t, err) c := "hello" - err = putFile(backend, "mybucket", "file1", "text/plain", c) + err = putFile(backend, "file1", "text/plain", c) require.NoError(t, err) c = `{"value": "goodbye world"}` - err = putFile(backend, "mybucket", "file2", "application/json", c) + err = putFile(backend, "file2", "application/json", c) require.NoError(t, err) c = `value: what a world` - err = putFile(backend, "mybucket", "file3", "application/yaml", c) + err = putFile(backend, "file3", "application/yaml", c) require.NoError(t, err) c = `value: out of this world` - err = putFile(backend, "mybucket", "dir1/file1", "application/yaml", c) + err = putFile(backend, "dir1/file1", "application/yaml", c) require.NoError(t, err) c = `value: foo` - err = putFile(backend, "mybucket", "dir1/file2", "application/yaml", c) + err = putFile(backend, "dir1/file2", "application/yaml", c) require.NoError(t, err) u, _ := url.Parse(ts.URL) return ts, u } -func putFile(backend gofakes3.Backend, bucket, file, mime, content string) error { +func putFile(backend gofakes3.Backend, file, mime, content string) error { _, err := backend.PutObject( - bucket, + "mybucket", file, map[string]string{"Content-Type": mime}, bytes.NewBufferString(content), diff --git a/data/datasource_env.go b/data/datasource_env.go index 70780f5ca..e5bf180f9 100644 --- a/data/datasource_env.go +++ b/data/datasource_env.go @@ -7,6 +7,7 @@ import ( "github.com/hairyhenderson/gomplate/v4/env" ) +//nolint:unparam func readEnv(_ context.Context, source *Source, _ ...string) (b []byte, err error) { n := source.URL.Path n = strings.TrimPrefix(n, "/") diff --git a/data/datasource_git.go b/data/datasource_git.go index 5c12da4cf..02df14be6 100644 --- a/data/datasource_git.go +++ b/data/datasource_git.go @@ -54,8 +54,7 @@ func readGit(ctx context.Context, source *Source, args ...string) ([]byte, error return out, err } -type gitsource struct { -} +type gitsource struct{} func (g gitsource) parseArgURL(arg string) (u *url.URL, err error) { if strings.HasPrefix(arg, "//") { @@ -136,7 +135,7 @@ func (g gitsource) parseGitPath(u *url.URL, args ...string) (out *url.URL, p str return out, p, err } -// nolint: interfacer +//nolint:interfacer func cloneURL(u *url.URL) *url.URL { out, _ := url.Parse(u.String()) return out diff --git a/data/datasource_git_test.go b/data/datasource_git_test.go index a5de9bc4e..3f74a620a 100644 --- a/data/datasource_git_test.go +++ b/data/datasource_git_test.go @@ -39,39 +39,61 @@ func TestParseArgPath(t *testing.T) { arg string repo, path string }{ - {"git+file:///foo//foo", + { + "git+file:///foo//foo", "/bar", - "", "/bar"}, - {"git+file:///foo//bar", + "", "/bar", + }, + { + "git+file:///foo//bar", "/baz//qux", - "", "/baz//qux"}, - {"git+https://example.com/foo", + "", "/baz//qux", + }, + { + "git+https://example.com/foo", "/bar", - "/bar", ""}, - {"git+https://example.com/foo", + "/bar", "", + }, + { + "git+https://example.com/foo", "//bar", - "", "//bar"}, - {"git+https://example.com/foo//bar", + "", "//bar", + }, + { + "git+https://example.com/foo//bar", "//baz", - "", "//baz"}, - {"git+https://example.com/foo", + "", "//baz", + }, + { + "git+https://example.com/foo", "/bar//baz", - "/bar", "/baz"}, - {"git+https://example.com/foo?type=t", + "/bar", "/baz", + }, + { + "git+https://example.com/foo?type=t", "/bar//baz", - "/bar", "/baz"}, - {"git+https://example.com/foo#master", + "/bar", "/baz", + }, + { + "git+https://example.com/foo#master", "/bar//baz", - "/bar", "/baz"}, - {"git+https://example.com/foo", + "/bar", "/baz", + }, + { + "git+https://example.com/foo", "//bar", - "", "//bar"}, - {"git+https://example.com/foo?type=t", + "", "//bar", + }, + { + "git+https://example.com/foo?type=t", "//baz", - "", "//baz"}, - {"git+https://example.com/foo?type=t#v1", + "", "//baz", + }, + { + "git+https://example.com/foo?type=t#v1", "//bar", - "", "//bar"}, + "", "//bar", + }, } for i, d := range data { @@ -103,76 +125,120 @@ func TestParseGitPath(t *testing.T) { args string repo, path string }{ - {"git+https://github.com/hairyhenderson/gomplate//docs-src/content/functions/aws.yml", + { + "git+https://github.com/hairyhenderson/gomplate//docs-src/content/functions/aws.yml", "", "git+https://github.com/hairyhenderson/gomplate", - "/docs-src/content/functions/aws.yml"}, - {"git+ssh://github.com/hairyhenderson/gomplate.git", + "/docs-src/content/functions/aws.yml", + }, + { + "git+ssh://github.com/hairyhenderson/gomplate.git", "", "git+ssh://github.com/hairyhenderson/gomplate.git", - "/"}, - {"https://github.com", + "/", + }, + { + "https://github.com", "", "https://github.com", - "/"}, - {"git://example.com/foo//file.txt#someref", + "/", + }, + { + "git://example.com/foo//file.txt#someref", "", - "git://example.com/foo#someref", "/file.txt"}, - {"git+file:///home/foo/repo//file.txt#someref", + "git://example.com/foo#someref", "/file.txt", + }, + { + "git+file:///home/foo/repo//file.txt#someref", "", - "git+file:///home/foo/repo#someref", "/file.txt"}, - {"git+file:///repo", + "git+file:///home/foo/repo#someref", "/file.txt", + }, + { + "git+file:///repo", "", - "git+file:///repo", "/"}, - {"git+file:///foo//foo", + "git+file:///repo", "/", + }, + { + "git+file:///foo//foo", "", - "git+file:///foo", "/foo"}, - {"git+file:///foo//foo", + "git+file:///foo", "/foo", + }, + { + "git+file:///foo//foo", "/bar", - "git+file:///foo", "/foo/bar"}, - {"git+file:///foo//bar", + "git+file:///foo", "/foo/bar", + }, + { + "git+file:///foo//bar", // in this case the // is meaningless "/baz//qux", - "git+file:///foo", "/bar/baz/qux"}, - {"git+https://example.com/foo", + "git+file:///foo", "/bar/baz/qux", + }, + { + "git+https://example.com/foo", "/bar", - "git+https://example.com/foo/bar", "/"}, - {"git+https://example.com/foo", + "git+https://example.com/foo/bar", "/", + }, + { + "git+https://example.com/foo", "//bar", - "git+https://example.com/foo", "/bar"}, - {"git+https://example.com//foo", + "git+https://example.com/foo", "/bar", + }, + { + "git+https://example.com//foo", "/bar", - "git+https://example.com", "/foo/bar"}, - {"git+https://example.com/foo//bar", + "git+https://example.com", "/foo/bar", + }, + { + "git+https://example.com/foo//bar", "//baz", - "git+https://example.com/foo", "/bar/baz"}, - {"git+https://example.com/foo", + "git+https://example.com/foo", "/bar/baz", + }, + { + "git+https://example.com/foo", "/bar//baz", - "git+https://example.com/foo/bar", "/baz"}, - {"git+https://example.com/foo?type=t", + "git+https://example.com/foo/bar", "/baz", + }, + { + "git+https://example.com/foo?type=t", "/bar//baz", - "git+https://example.com/foo/bar?type=t", "/baz"}, - {"git+https://example.com/foo#master", + "git+https://example.com/foo/bar?type=t", "/baz", + }, + { + "git+https://example.com/foo#master", "/bar//baz", - "git+https://example.com/foo/bar#master", "/baz"}, - {"git+https://example.com/foo", + "git+https://example.com/foo/bar#master", "/baz", + }, + { + "git+https://example.com/foo", "/bar//baz?type=t", - "git+https://example.com/foo/bar?type=t", "/baz"}, - {"git+https://example.com/foo", + "git+https://example.com/foo/bar?type=t", "/baz", + }, + { + "git+https://example.com/foo", "/bar//baz#master", - "git+https://example.com/foo/bar#master", "/baz"}, - {"git+https://example.com/foo", + "git+https://example.com/foo/bar#master", "/baz", + }, + { + "git+https://example.com/foo", "//bar?type=t", - "git+https://example.com/foo?type=t", "/bar"}, - {"git+https://example.com/foo", + "git+https://example.com/foo?type=t", "/bar", + }, + { + "git+https://example.com/foo", "//bar#master", - "git+https://example.com/foo#master", "/bar"}, - {"git+https://example.com/foo?type=t", + "git+https://example.com/foo#master", "/bar", + }, + { + "git+https://example.com/foo?type=t", "//bar#master", - "git+https://example.com/foo?type=t#master", "/bar"}, - {"git+https://example.com/foo?type=t#v1", + "git+https://example.com/foo?type=t#master", "/bar", + }, + { + "git+https://example.com/foo?type=t#v1", "//bar?type=j#v2", - "git+https://example.com/foo?type=t&type=j#v2", "/bar"}, + "git+https://example.com/foo?type=t&type=j#v2", "/bar", + }, } for i, d := range data { diff --git a/data/datasource_http_test.go b/data/datasource_http_test.go index a742d9e5f..90c4a7f98 100644 --- a/data/datasource_http_test.go +++ b/data/datasource_http_test.go @@ -22,7 +22,6 @@ func must(r interface{}, err error) interface{} { func setupHTTP(code int, mimetype string, body string) (*httptest.Server, *http.Client) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", mimetype) w.WriteHeader(code) if body == "" { diff --git a/data/datasource_test.go b/data/datasource_test.go index 43d59c858..a77f26457 100644 --- a/data/datasource_test.go +++ b/data/datasource_test.go @@ -246,24 +246,36 @@ func TestMimeType(t *testing.T) { mediaType string expected string }{ - {"http://example.com/foo.json", + { + "http://example.com/foo.json", "", - jsonMimetype}, - {"http://example.com/foo.json", + jsonMimetype, + }, + { + "http://example.com/foo.json", "text/foo", - "text/foo"}, - {"http://example.com/foo.json?type=application/yaml", "text/foo", - "application/yaml"}, - {"http://example.com/list?type=application/array%2Bjson", + }, + { + "http://example.com/foo.json?type=application/yaml", "text/foo", - "application/array+json"}, - {"http://example.com/list?type=application/array+json", + "application/yaml", + }, + { + "http://example.com/list?type=application/array%2Bjson", + "text/foo", + "application/array+json", + }, + { + "http://example.com/list?type=application/array+json", "", - "application/array+json"}, - {"http://example.com/unknown", + "application/array+json", + }, + { + "http://example.com/unknown", "", - "text/plain"}, + "text/plain", + }, } for i, d := range data { @@ -288,38 +300,54 @@ func TestMimeTypeWithArg(t *testing.T) { arg string expected string }{ - {"http://example.com/unknown", + { + "http://example.com/unknown", "", "/foo.json", - "application/json"}, - {"http://example.com/unknown", + "application/json", + }, + { + "http://example.com/unknown", "", "foo.json", - "application/json"}, - {"http://example.com/", + "application/json", + }, + { + "http://example.com/", "text/foo", "/foo.json", - "text/foo"}, - {"git+https://example.com/myrepo", + "text/foo", + }, + { + "git+https://example.com/myrepo", "", "//foo.yaml", - "application/yaml"}, - {"http://example.com/foo.json", + "application/yaml", + }, + { + "http://example.com/foo.json", "", "/foo.yaml", - "application/yaml"}, - {"http://example.com/foo.json?type=application/array+yaml", + "application/yaml", + }, + { + "http://example.com/foo.json?type=application/array+yaml", "", "/foo.yaml", - "application/array+yaml"}, - {"http://example.com/foo.json?type=application/array+yaml", + "application/array+yaml", + }, + { + "http://example.com/foo.json?type=application/array+yaml", "", "/foo.yaml?type=application/yaml", - "application/yaml"}, - {"http://example.com/foo.json?type=application/array+yaml", + "application/yaml", + }, + { + "http://example.com/foo.json?type=application/array+yaml", "text/plain", "/foo.yaml?type=application/yaml", - "application/yaml"}, + "application/yaml", + }, } for i, d := range data { diff --git a/funcs.go b/funcs.go index 6e0241848..8a665cdd5 100644 --- a/funcs.go +++ b/funcs.go @@ -17,9 +17,9 @@ func Funcs(d *data.Data) template.FuncMap { } // CreateFuncs - function mappings are created here -func CreateFuncs(ctx context.Context, - //nolint:staticcheck - d *data.Data) template.FuncMap { +// +//nolint:staticcheck +func CreateFuncs(ctx context.Context, d *data.Data) template.FuncMap { f := template.FuncMap{} addToMap(f, funcs.CreateDataFuncs(ctx, d)) addToMap(f, funcs.CreateAWSFuncs(ctx)) diff --git a/funcs/crypto.go b/funcs/crypto.go index bfb134834..41c752c78 100644 --- a/funcs/crypto.go +++ b/funcs/crypto.go @@ -76,7 +76,6 @@ func (f CryptoFuncs) WPAPSK(ssid, password interface{}) (string, error) { // SHA1 - Note: SHA-1 is cryptographically broken and should not be used for secure applications. func (f CryptoFuncs) SHA1(input interface{}) string { - // nolint: gosec out, _ := f.SHA1Bytes(input) return fmt.Sprintf("%02x", out) } @@ -106,14 +105,16 @@ func (f CryptoFuncs) SHA512(input interface{}) string { } // SHA512_224 - -// nolint: revive,stylecheck +// +//nolint:revive,stylecheck func (f CryptoFuncs) SHA512_224(input interface{}) string { out, _ := f.SHA512_224Bytes(input) return fmt.Sprintf("%02x", out) } // SHA512_256 - -// nolint: revive,stylecheck +// +//nolint:revive,stylecheck func (f CryptoFuncs) SHA512_256(input interface{}) string { out, _ := f.SHA512_256Bytes(input) return fmt.Sprintf("%02x", out) @@ -161,7 +162,6 @@ func (CryptoFuncs) SHA512Bytes(input interface{}) ([]byte, error) { } // SHA512_224 - -// nolint: revive,stylecheck func (CryptoFuncs) SHA512_224Bytes(input interface{}) ([]byte, error) { b := sha512.Sum512_224(toBytes(input)) out := make([]byte, len(b)) @@ -170,7 +170,6 @@ func (CryptoFuncs) SHA512_224Bytes(input interface{}) ([]byte, error) { } // SHA512_256 - -// nolint: revive,stylecheck func (CryptoFuncs) SHA512_256Bytes(input interface{}) ([]byte, error) { b := sha512.Sum512_256(toBytes(input)) out := make([]byte, len(b)) @@ -265,7 +264,7 @@ func (f *CryptoFuncs) ECDSAGenerateKey(args ...interface{}) (string, error) { c = strings.ToUpper(c) c = strings.ReplaceAll(c, "-", "") var ok bool - curve, ok = crypto.Curves[c] + curve, ok = crypto.Curves(c) if !ok { return "", fmt.Errorf("unknown curve: %s", c) } diff --git a/funcs/crypto_test.go b/funcs/crypto_test.go index 93cadb414..90f6bdff5 100644 --- a/funcs/crypto_test.go +++ b/funcs/crypto_test.go @@ -55,7 +55,6 @@ func TestWPAPSK(t *testing.T) { require.NoError(t, err) } -//nolint:gosec func TestSHA(t *testing.T) { t.Parallel() diff --git a/funcs/data.go b/funcs/data.go index bb47988b8..e9ce7fa5a 100644 --- a/funcs/data.go +++ b/funcs/data.go @@ -24,9 +24,9 @@ func AddDataFuncs(f map[string]interface{}, d *data.Data) { } // CreateDataFuncs - -func CreateDataFuncs(ctx context.Context, - //nolint:staticcheck - d *data.Data) map[string]interface{} { +// +//nolint:staticcheck +func CreateDataFuncs(ctx context.Context, d *data.Data) map[string]interface{} { f := map[string]interface{}{} f["datasource"] = d.Datasource f["ds"] = d.Datasource diff --git a/funcs/file_test.go b/funcs/file_test.go index a198a0603..d9fe5ccc7 100644 --- a/funcs/file_test.go +++ b/funcs/file_test.go @@ -129,8 +129,8 @@ func TestWrite(t *testing.T) { newwd := rootDir.Join("the", "path", "we", "want") badwd := rootDir.Join("some", "other", "dir") - hackpadfs.MkdirAll(fsys, newwd, 0755) - hackpadfs.MkdirAll(fsys, badwd, 0755) + hackpadfs.MkdirAll(fsys, newwd, 0o755) + hackpadfs.MkdirAll(fsys, badwd, 0o755) newwd, _ = filepath.EvalSymlinks(newwd) badwd, _ = filepath.EvalSymlinks(badwd) diff --git a/funcs/gcp.go b/funcs/gcp.go index 7bd2997fb..040a451be 100644 --- a/funcs/gcp.go +++ b/funcs/gcp.go @@ -38,19 +38,15 @@ func CreateGCPFuncs(ctx context.Context) map[string]interface{} { type GcpFuncs struct { ctx context.Context - meta *gcp.MetaClient - metaInit sync.Once - gcpopts gcp.ClientOptions + meta *gcp.MetaClient + gcpopts gcp.ClientOptions } // Meta - func (a *GcpFuncs) Meta(key string, def ...string) (string, error) { - a.metaInit.Do(a.initGcpMeta) - return a.meta.Meta(key, def...) -} + a.meta = sync.OnceValue[*gcp.MetaClient](func() *gcp.MetaClient { + return gcp.NewMetaClient(a.ctx, a.gcpopts) + })() -func (a *GcpFuncs) initGcpMeta() { - if a.meta == nil { - a.meta = gcp.NewMetaClient(a.gcpopts) - } + return a.meta.Meta(key, def...) } diff --git a/funcs/math_test.go b/funcs/math_test.go index e816bb86a..45681e21a 100644 --- a/funcs/math_test.go +++ b/funcs/math_test.go @@ -105,6 +105,7 @@ func mustSeq(t *testing.T, n ...interface{}) []int64 { } return s } + func TestSeq(t *testing.T) { t.Parallel() diff --git a/funcs/net.go b/funcs/net.go index 3f5120232..3342bd27c 100644 --- a/funcs/net.go +++ b/funcs/net.go @@ -136,8 +136,6 @@ func (f NetFuncs) ParseRange(iprange interface{}) (netipx.IPRange, error) { // } // TODO: look at using this instead of parseStdnetIPNet -// -//nolint:unused func (f *NetFuncs) parseNetipPrefix(prefix interface{}) (netip.Prefix, error) { switch p := prefix.(type) { case *stdnet.IPNet: diff --git a/funcs/net_test.go b/funcs/net_test.go index 3e248a60d..7c3afffe6 100644 --- a/funcs/net_test.go +++ b/funcs/net_test.go @@ -130,6 +130,7 @@ func TestParseRange(t *testing.T) { require.NoError(t, err) assert.Equal(t, "192.168.0.2-192.168.23.255", iprange.String()) } + func testNetNS() *NetFuncs { return &NetFuncs{ctx: config.SetExperimental(context.Background())} } diff --git a/funcs/random_test.go b/funcs/random_test.go index 7f101b988..7f166ffc2 100644 --- a/funcs/random_test.go +++ b/funcs/random_test.go @@ -98,8 +98,8 @@ func TestToCodePoints(t *testing.T) { l, u, err = toCodePoints("0011", "0777") require.NoError(t, err) - assert.Equal(t, rune(0011), l) - assert.Equal(t, rune(0777), u) + assert.Equal(t, rune(0o011), l) + assert.Equal(t, rune(0o777), u) l, u, err = toCodePoints("♬", "♟") require.NoError(t, err) diff --git a/gcp/meta.go b/gcp/meta.go index 61bc6a8a2..872c9359f 100644 --- a/gcp/meta.go +++ b/gcp/meta.go @@ -1,6 +1,7 @@ package gcp import ( + "context" "fmt" "io" "net/http" @@ -49,6 +50,7 @@ func GetClientOptions() ClientOptions { // MetaClient is used to access metadata accessible via the GCP compute instance // metadata service version 1. type MetaClient struct { + ctx context.Context client *http.Client cache map[string]string endpoint string @@ -58,13 +60,14 @@ type MetaClient struct { // NewMetaClient constructs a new MetaClient with the given ClientOptions. If the environment // contains a variable named `GCP_META_ENDPOINT`, the client will address that, if not the // value of `DefaultEndpoint` is used. -func NewMetaClient(options ClientOptions) *MetaClient { +func NewMetaClient(ctx context.Context, options ClientOptions) *MetaClient { endpoint := env.Getenv("GCP_META_ENDPOINT") if endpoint == "" { endpoint = DefaultEndpoint } return &MetaClient{ + ctx: ctx, cache: make(map[string]string), endpoint: endpoint, options: options, @@ -75,12 +78,12 @@ func NewMetaClient(options ClientOptions) *MetaClient { // if the service is unavailable or the requested URL does not exist. func (c *MetaClient) Meta(key string, def ...string) (string, error) { url := c.endpoint + "/computeMetadata/v1/instance/" + key - return c.retrieveMetadata(url, def...) + return c.retrieveMetadata(c.ctx, url, def...) } // retrieveMetadata executes an HTTP request to the GCP Instance Metadata Service with the // correct headers set, and extracts the returned value. -func (c *MetaClient) retrieveMetadata(url string, def ...string) (string, error) { +func (c *MetaClient) retrieveMetadata(ctx context.Context, url string, def ...string) (string, error) { if value, ok := c.cache[url]; ok { return value, nil } @@ -93,7 +96,7 @@ func (c *MetaClient) retrieveMetadata(url string, def ...string) (string, error) c.client = &http.Client{Timeout: timeout} } - request, err := http.NewRequest(http.MethodGet, url, nil) + request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) if err != nil { return returnDefault(def), nil } @@ -104,7 +107,6 @@ func (c *MetaClient) retrieveMetadata(url string, def ...string) (string, error) return returnDefault(def), nil } - // nolint: errcheck defer resp.Body.Close() if resp.StatusCode > 399 { return returnDefault(def), nil diff --git a/gomplate.go b/gomplate.go index 6a9f8028a..f95dc2a34 100644 --- a/gomplate.go +++ b/gomplate.go @@ -96,7 +96,7 @@ func mappingNamer(outMap string, tr *Renderer) func(context.Context, string) (st // add '.in' to the template context and preserve the original context // in '.ctx' tctx := &tmplctx{} - // nolint: gocritic + //nolint:gocritic switch c := tcontext.(type) { case *tmplctx: for k, v := range *c { diff --git a/gomplate_test.go b/gomplate_test.go index f3f6f1589..7ce6efe97 100644 --- a/gomplate_test.go +++ b/gomplate_test.go @@ -6,7 +6,6 @@ import ( "os" "path/filepath" "testing" - "text/template" "github.com/hairyhenderson/gomplate/v4/aws" diff --git a/internal/cmd/main.go b/internal/cmd/main.go index e09ee863f..7533f8555 100644 --- a/internal/cmd/main.go +++ b/internal/cmd/main.go @@ -29,7 +29,7 @@ func postRunExec(ctx context.Context, args []string, stdin io.Reader, stdout, st name := args[0] args = args[1:] - // nolint: gosec + c := exec.CommandContext(ctx, name, args...) c.Stdin = stdin c.Stderr = stderr @@ -49,7 +49,6 @@ func postRunExec(ctx context.Context, args []string, stdin io.Reader, stdout, st case sig := <-sigs: // Pass signals to the sub-process if c.Process != nil { - // nolint: gosec _ = c.Process.Signal(sig) } case <-ctx.Done(): diff --git a/internal/config/configfile.go b/internal/config/configfile.go index 763520dec..32067c8f6 100644 --- a/internal/config/configfile.go +++ b/internal/config/configfile.go @@ -254,17 +254,17 @@ func (c *Config) MergeFrom(o *Config) *Config { if c.Templates == nil { c.Templates = o.Templates } else { - mergeDataSources(c.Templates, o.Templates) + c.Templates = mergeDataSources(c.Templates, o.Templates) } if c.DataSources == nil { c.DataSources = o.DataSources } else { - mergeDataSources(c.DataSources, o.DataSources) + c.DataSources = mergeDataSources(c.DataSources, o.DataSources) } if c.Context == nil { c.Context = o.Context } else { - mergeDataSources(c.Context, o.Context) + c.Context = mergeDataSources(c.Context, o.Context) } if len(o.Plugins) > 0 { for k, v := range o.Plugins { @@ -559,7 +559,7 @@ func (c *Config) GetMode() (os.FileMode, bool, error) { } mode := iohelpers.NormalizeFileMode(os.FileMode(m)) if mode == 0 && c.Input != "" { - mode = iohelpers.NormalizeFileMode(0644) + mode = iohelpers.NormalizeFileMode(0o644) } return mode, modeOverride, nil } diff --git a/internal/config/configfile_test.go b/internal/config/configfile_test.go index 8fe176932..e99fc8b47 100644 --- a/internal/config/configfile_test.go +++ b/internal/config/configfile_test.go @@ -471,8 +471,11 @@ func TestParseDataSourceFlags(t *testing.T) { []string{"baz=foo/bar/baz.json"}, []string{"foo=http://example.com"}, nil, - []string{"foo=Accept: application/json", - "bar=Authorization: Basic xxxxx"}) + []string{ + "foo=Accept: application/json", + "bar=Authorization: Basic xxxxx", + }, + ) require.NoError(t, err) assert.EqualValues(t, &Config{ DataSources: map[string]DataSource{ @@ -496,8 +499,8 @@ func TestParseDataSourceFlags(t *testing.T) { nil, nil, []string{"foo=http://example.com", "file.tmpl", "tmpldir/"}, - []string{"foo=Accept: application/json", - "bar=Authorization: Basic xxxxx"}) + []string{"foo=Accept: application/json", "bar=Authorization: Basic xxxxx"}, + ) require.NoError(t, err) assert.EqualValues(t, &Config{ Templates: Templates{ diff --git a/internal/config/types_test.go b/internal/config/types_test.go index b72412004..47942c2f9 100644 --- a/internal/config/types_test.go +++ b/internal/config/types_test.go @@ -76,8 +76,10 @@ func TestParseTemplateArg(t *testing.T) { {in: "templatedir/", alias: "templatedir/", ds: DataSource{URL: mustURL("templatedir/")}}, {in: "dir=foo/bar/", alias: "dir", ds: DataSource{URL: mustURL("foo/bar/")}}, {in: "mytemplate.t", alias: "mytemplate.t", ds: DataSource{URL: mustURL("mytemplate.t")}}, - {in: "remote=https://example.com/foo/bar/helloworld.tmpl", - alias: "remote", ds: DataSource{URL: mustURL("https://example.com/foo/bar/helloworld.tmpl")}}, + { + in: "remote=https://example.com/foo/bar/helloworld.tmpl", + alias: "remote", ds: DataSource{URL: mustURL("https://example.com/foo/bar/helloworld.tmpl")}, + }, } for _, d := range data { diff --git a/internal/iohelpers/writers_test.go b/internal/iohelpers/writers_test.go index 415634d55..8a9c68e05 100644 --- a/internal/iohelpers/writers_test.go +++ b/internal/iohelpers/writers_test.go @@ -179,8 +179,8 @@ func TestWrite(t *testing.T) { newwd := rootDir.Join("the", "path", "we", "want") badwd := rootDir.Join("some", "other", "dir") - hackpadfs.MkdirAll(fsys, newwd, 0755) - hackpadfs.MkdirAll(fsys, badwd, 0755) + hackpadfs.MkdirAll(fsys, newwd, 0o755) + hackpadfs.MkdirAll(fsys, badwd, 0o755) newwd, _ = filepath.EvalSymlinks(newwd) badwd, _ = filepath.EvalSymlinks(badwd) diff --git a/internal/tests/integration/basic_test.go b/internal/tests/integration/basic_test.go index e4cb046ea..49a3b168e 100644 --- a/internal/tests/integration/basic_test.go +++ b/internal/tests/integration/basic_test.go @@ -83,8 +83,8 @@ func TestBasic_RoutesInputsToProperOutputs(t *testing.T) { content string mode os.FileMode }{ - {oneOut, "hi\n", 0640}, - {twoOut, "hello\n", 0644}, + {oneOut, "hi\n", 0o640}, + {twoOut, "hello\n", 0o644}, } for _, v := range testdata { info, err := os.Stat(v.path) @@ -204,8 +204,8 @@ func TestBasic_RoutesInputsToProperOutputsWithChmod(t *testing.T) { content string mode os.FileMode }{ - {oneOut, "hi\n", 0600}, - {twoOut, "hello\n", 0600}, + {oneOut, "hi\n", 0o600}, + {twoOut, "hello\n", 0o600}, } for _, v := range testdata { info, err := os.Stat(v.path) @@ -233,7 +233,7 @@ func TestBasic_OverridesOutputModeWithChmod(t *testing.T) { content string mode os.FileMode }{ - {out, "hi\n", 0600}, + {out, "hi\n", 0o600}, } for _, v := range testdata { info, err := os.Stat(v.path) @@ -258,7 +258,7 @@ func TestBasic_AppliesChmodBeforeWrite(t *testing.T) { info, err := os.Stat(out) assert.NilError(t, err) - assert.Equal(t, iohelpers.NormalizeFileMode(0644), info.Mode()) + assert.Equal(t, iohelpers.NormalizeFileMode(0o644), info.Mode()) content, err := os.ReadFile(out) assert.NilError(t, err) assert.Equal(t, "hi\n", string(content)) @@ -272,7 +272,7 @@ func TestBasic_CreatesMissingDirectory(t *testing.T) { info, err := os.Stat(out) assert.NilError(t, err) - assert.Equal(t, iohelpers.NormalizeFileMode(0640), info.Mode()) + assert.Equal(t, iohelpers.NormalizeFileMode(0o640), info.Mode()) content, err := os.ReadFile(out) assert.NilError(t, err) assert.Equal(t, "hi\n", string(content)) diff --git a/internal/tests/integration/config_test.go b/internal/tests/integration/config_test.go index cccc0d973..fd7db539a 100644 --- a/internal/tests/integration/config_test.go +++ b/internal/tests/integration/config_test.go @@ -16,7 +16,7 @@ func setupConfigTest(t *testing.T) *tfs.Dir { tfs.WithDir("indir"), tfs.WithDir("outdir"), tfs.WithFile(".gomplate.yaml", "in: hello world\n"), - tfs.WithFile("sleep.sh", "#!/bin/sh\n\nexec sleep $1\n", tfs.WithMode(0755)), + tfs.WithFile("sleep.sh", "#!/bin/sh\n\nexec sleep $1\n", tfs.WithMode(0o755)), ) t.Cleanup(tmpDir.Remove) return tmpDir @@ -26,7 +26,7 @@ func writeFile(t *testing.T, dir *tfs.Dir, f, content string) { t.Helper() f = dir.Join(f) - err := os.WriteFile(f, []byte(content), 0600) + err := os.WriteFile(f, []byte(content), 0o600) if err != nil { t.Fatal(err) } diff --git a/internal/tests/integration/datasources_env_test.go b/internal/tests/integration/datasources_env_test.go index 6a17abed5..81aad3947 100644 --- a/internal/tests/integration/datasources_env_test.go +++ b/internal/tests/integration/datasources_env_test.go @@ -5,7 +5,6 @@ import ( ) func TestDatasources_Env(t *testing.T) { - o, e, err := cmd(t, "-d", "foo=env:FOO", "-i", `{{ ds "foo" }}`). withEnv("HELLO_WORLD", "hello world"). withEnv("HELLO_UNIVERSE", "hello universe"). diff --git a/internal/tests/integration/datasources_vault_test.go b/internal/tests/integration/datasources_vault_test.go index ee105b6dc..39ccb5499 100644 --- a/internal/tests/integration/datasources_vault_test.go +++ b/internal/tests/integration/datasources_vault_test.go @@ -149,10 +149,12 @@ func TestDatasources_Vault_UserPassAuth(t *testing.T) { defer v.vc.Sys().DisableAuth("userpass") defer v.vc.Sys().DisableAuth("userpass2") _, err = v.vc.Logical().Write("auth/userpass/users/dave", map[string]interface{}{ - "password": "foo", "ttl": "10s", "policies": "readpol"}) + "password": "foo", "ttl": "10s", "policies": "readpol", + }) require.NoError(t, err) _, err = v.vc.Logical().Write("auth/userpass2/users/dave", map[string]interface{}{ - "password": "bar", "ttl": "10s", "policies": "readpol"}) + "password": "bar", "ttl": "10s", "policies": "readpol", + }) require.NoError(t, err) o, e, err := cmd(t, "-d", "vault=vault:///secret", diff --git a/internal/tests/integration/file_test.go b/internal/tests/integration/file_test.go index ce33fabce..fde7c6edb 100644 --- a/internal/tests/integration/file_test.go +++ b/internal/tests/integration/file_test.go @@ -28,7 +28,7 @@ func TestFile_Write(t *testing.T) { tmpDir := setupFileTest(t) outDir := tmpDir.Join("writeOutput") - os.MkdirAll(outDir, 0755) + os.MkdirAll(outDir, 0o755) o, e, err := cmd(t, "-i", `{{ "hello world" | file.Write "./out" }}`). withDir(outDir).run() assertSuccess(t, o, e, err, "") diff --git a/internal/tests/integration/inputdir_test.go b/internal/tests/integration/inputdir_test.go index d430cf948..39dd30db7 100644 --- a/internal/tests/integration/inputdir_test.go +++ b/internal/tests/integration/inputdir_test.go @@ -19,12 +19,12 @@ func setupInputDirTest(t *testing.T) *fs.Dir { out/{{ .in | strings.ReplaceAll $f (index .filemap $f) }}.out `), fs.WithDir("in", - fs.WithFile("eins.txt", `{{ (ds "config").one }}`, fs.WithMode(0644)), + fs.WithFile("eins.txt", `{{ (ds "config").one }}`, fs.WithMode(0o644)), fs.WithDir("inner", - fs.WithFile("deux.txt", `{{ (ds "config").two }}`, fs.WithMode(0444)), + fs.WithFile("deux.txt", `{{ (ds "config").two }}`, fs.WithMode(0o444)), ), - fs.WithFile("drei.sh", `#!/bin/sh\necho "hello world"\n`, fs.WithMode(0755)), - fs.WithFile("vier.txt", `{{ (ds "config").two }} * {{ (ds "config").two }}`, fs.WithMode(0544)), + fs.WithFile("drei.sh", `#!/bin/sh\necho "hello world"\n`, fs.WithMode(0o755)), + fs.WithFile("vier.txt", `{{ (ds "config").two }} * {{ (ds "config").two }}`, fs.WithMode(0o544)), ), fs.WithDir("out"), fs.WithDir("bad_in", @@ -59,10 +59,10 @@ func TestInputDir_InputDir(t *testing.T) { content string mode os.FileMode }{ - {tmpDir.Join("out", "eins.txt"), "eins", 0644}, - {tmpDir.Join("out", "inner", "deux.txt"), "deux", 0444}, - {tmpDir.Join("out", "drei.sh"), `#!/bin/sh\necho "hello world"\n`, 0755}, - {tmpDir.Join("out", "vier.txt"), "deux * deux", 0544}, + {tmpDir.Join("out", "eins.txt"), "eins", 0o644}, + {tmpDir.Join("out", "inner", "deux.txt"), "deux", 0o444}, + {tmpDir.Join("out", "drei.sh"), `#!/bin/sh\necho "hello world"\n`, 0o755}, + {tmpDir.Join("out", "vier.txt"), "deux * deux", 0o544}, } for _, v := range testdata { info, err := os.Stat(v.path) @@ -98,10 +98,10 @@ func TestInputDir_InputDirWithModeOverride(t *testing.T) { content string mode os.FileMode }{ - {tmpDir.Join("out", "eins.txt"), "eins", 0601}, - {tmpDir.Join("out", "inner", "deux.txt"), "deux", 0601}, - {tmpDir.Join("out", "drei.sh"), `#!/bin/sh\necho "hello world"\n`, 0601}, - {tmpDir.Join("out", "vier.txt"), "deux * deux", 0601}, + {tmpDir.Join("out", "eins.txt"), "eins", 0o601}, + {tmpDir.Join("out", "inner", "deux.txt"), "deux", 0o601}, + {tmpDir.Join("out", "drei.sh"), `#!/bin/sh\necho "hello world"\n`, 0o601}, + {tmpDir.Join("out", "vier.txt"), "deux * deux", 0o601}, } for _, v := range testdata { info, err := os.Stat(v.path) @@ -136,10 +136,10 @@ func TestInputDir_OutputMapInline(t *testing.T) { content string mode os.FileMode }{ - {tmpDir.Join("OUT", "EINS.TXT"), "eins", 0644}, - {tmpDir.Join("OUT", "INNER", "DEUX.TXT"), "deux", 0444}, - {tmpDir.Join("OUT", "DREI.SH"), `#!/bin/sh\necho "hello world"\n`, 0755}, - {tmpDir.Join("OUT", "VIER.TXT"), "deux * deux", 0544}, + {tmpDir.Join("OUT", "EINS.TXT"), "eins", 0o644}, + {tmpDir.Join("OUT", "INNER", "DEUX.TXT"), "deux", 0o444}, + {tmpDir.Join("OUT", "DREI.SH"), `#!/bin/sh\necho "hello world"\n`, 0o755}, + {tmpDir.Join("OUT", "VIER.TXT"), "deux * deux", 0o544}, } for _, v := range testdata { info, err := os.Stat(v.path) @@ -176,10 +176,10 @@ func TestInputDir_OutputMapExternal(t *testing.T) { content string mode os.FileMode }{ - {tmpDir.Join("out", "uno.out"), "eins", 0644}, - {tmpDir.Join("out", "inner", "dos.out"), "deux", 0444}, - {tmpDir.Join("out", "tres.out"), `#!/bin/sh\necho "hello world"\n`, 0755}, - {tmpDir.Join("out", "quatro.out"), "deux * deux", 0544}, + {tmpDir.Join("out", "uno.out"), "eins", 0o644}, + {tmpDir.Join("out", "inner", "dos.out"), "deux", 0o444}, + {tmpDir.Join("out", "tres.out"), `#!/bin/sh\necho "hello world"\n`, 0o755}, + {tmpDir.Join("out", "quatro.out"), "deux * deux", 0o544}, } for _, v := range testdata { info, err := os.Stat(v.path) @@ -251,9 +251,9 @@ func TestInputDir_InputDirCwd(t *testing.T) { content string mode os.FileMode }{ - {tmpDir.Join("in", "eins.out"), "eins", 0644}, - {tmpDir.Join("in", "inner", "deux.out"), "deux", 0444}, - {tmpDir.Join("in", "vier.out"), "deux * deux", 0544}, + {tmpDir.Join("in", "eins.out"), "eins", 0o644}, + {tmpDir.Join("in", "inner", "deux.out"), "deux", 0o444}, + {tmpDir.Join("in", "vier.out"), "deux * deux", 0o544}, } for _, v := range testdata { info, err := os.Stat(v.path) diff --git a/internal/tests/integration/integration_test.go b/internal/tests/integration/integration_test.go index 1e56e0096..bc79862ac 100644 --- a/internal/tests/integration/integration_test.go +++ b/internal/tests/integration/integration_test.go @@ -92,12 +92,20 @@ func freeport(t *testing.T) (port int, addr string) { // waitForURL - waits up to 20s for a given URL to respond with a 200 func waitForURL(t *testing.T, url string) error { + ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) + defer cancel() + client := http.DefaultClient retries := 100 for retries > 0 { retries-- time.Sleep(200 * time.Millisecond) - resp, err := client.Get(url) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) + if err != nil { + return err + } + + resp, err := client.Do(req) if err != nil { t.Logf("Got error, retries left: %d (error: %v)", retries, err) continue diff --git a/internal/tests/integration/plugins_test.go b/internal/tests/integration/plugins_test.go index 82d571ffa..8a833cde5 100644 --- a/internal/tests/integration/plugins_test.go +++ b/internal/tests/integration/plugins_test.go @@ -12,10 +12,10 @@ import ( func setupPluginsTest(t *testing.T) *fs.Dir { tmpDir := fs.NewDir(t, "gomplate-inttests", - fs.WithFile("foo.sh", "#!/bin/sh\n\necho $*\n", fs.WithMode(0755)), - fs.WithFile("foo.ps1", "echo $args\r\n", fs.WithMode(0755)), - fs.WithFile("bar.sh", "#!/bin/sh\n\neval \"echo $*\"\n", fs.WithMode(0755)), - fs.WithFile("fail.sh", "#!/bin/sh\n\n>&2 echo $1\nexit $2\n", fs.WithMode(0755)), + fs.WithFile("foo.sh", "#!/bin/sh\n\necho $*\n", fs.WithMode(0o755)), + fs.WithFile("foo.ps1", "echo $args\r\n", fs.WithMode(0o755)), + fs.WithFile("bar.sh", "#!/bin/sh\n\neval \"echo $*\"\n", fs.WithMode(0o755)), + fs.WithFile("fail.sh", "#!/bin/sh\n\n>&2 echo $1\nexit $2\n", fs.WithMode(0o755)), fs.WithFile("fail.ps1", `param ( [Parameter(Position=0)] [string]$msg, @@ -25,15 +25,15 @@ func setupPluginsTest(t *testing.T) *fs.Dir { ) write-error $msg exit $code -`, fs.WithMode(0755)), - fs.WithFile("sleep.sh", "#!/bin/sh\n\nexec sleep $1\n", fs.WithMode(0755)), +`, fs.WithMode(0o755)), + fs.WithFile("sleep.sh", "#!/bin/sh\n\nexec sleep $1\n", fs.WithMode(0o755)), fs.WithFile("replace.sh", `#!/bin/sh if [ "$#" -eq 2 ]; then exec tr $1 $2 elif [ "$#" -eq 3 ]; then printf "=%s" $3 | tr $1 $2 fi -`, fs.WithMode(0755)), +`, fs.WithMode(0o755)), ) t.Cleanup(tmpDir.Remove) diff --git a/internal/tests/integration/plugins_windows_test.go b/internal/tests/integration/plugins_windows_test.go index c8411876b..a00cc6d88 100644 --- a/internal/tests/integration/plugins_windows_test.go +++ b/internal/tests/integration/plugins_windows_test.go @@ -13,12 +13,12 @@ import ( func setupPluginsTest(t *testing.T) *fs.Dir { tmpDir := fs.NewDir(t, "gomplate-inttests", - fs.WithFile("foo.ps1", "echo $args\r\nexit 0\r\n", fs.WithMode(0644)), - fs.WithFile("foo.bat", "@ECHO OFF\r\nECHO %1\r\n", fs.WithMode(0644)), + fs.WithFile("foo.ps1", "echo $args\r\nexit 0\r\n", fs.WithMode(0o644)), + fs.WithFile("foo.bat", "@ECHO OFF\r\nECHO %1\r\n", fs.WithMode(0o644)), fs.WithFile("fail.bat", `@ECHO OFF ECHO %1 1>&2 EXIT /B %2 -`, fs.WithMode(0755)), +`, fs.WithMode(0o755)), fs.WithFile("fail.ps1", `param ( [Parameter(Position=0)] [string]$msg, @@ -28,7 +28,7 @@ EXIT /B %2 ) $host.ui.WriteErrorLine($msg) $host.SetShouldExit($code) -`, fs.WithMode(0755)), +`, fs.WithMode(0o755)), ) t.Cleanup(tmpDir.Remove) diff --git a/internal/tests/integration/tmpl_test.go b/internal/tests/integration/tmpl_test.go index c35f01675..dc27e7511 100644 --- a/internal/tests/integration/tmpl_test.go +++ b/internal/tests/integration/tmpl_test.go @@ -71,7 +71,7 @@ func TestTmpl_Exec(t *testing.T) { `) outDir := tmpDir.Join("out") - err = os.MkdirAll(outDir, 0755) + err = os.MkdirAll(outDir, 0o755) if err != nil { assert.NilError(t, err) } diff --git a/libkv/consul.go b/libkv/consul.go index 7875e63df..c47fb798d 100644 --- a/libkv/consul.go +++ b/libkv/consul.go @@ -48,7 +48,6 @@ func NewConsul(u *url.URL) (*LibKV, error) { if token != "" { // set CONSUL_HTTP_TOKEN before creating the client - // nolint: gosec _ = os.Setenv(consulapi.HTTPTokenEnvName, token) } diff --git a/net/net_test.go b/net/net_test.go index 41f53d140..baae8c01d 100644 --- a/net/net_test.go +++ b/net/net_test.go @@ -13,6 +13,7 @@ func must(r interface{}, err error) interface{} { } return r } + func TestLookupIP(t *testing.T) { assert.Equal(t, "127.0.0.1", must(LookupIP("localhost"))) assert.Equal(t, "93.184.216.34", must(LookupIP("example.com"))) diff --git a/plugins.go b/plugins.go index 50e34bf55..7509b97c9 100644 --- a/plugins.go +++ b/plugins.go @@ -165,7 +165,6 @@ func (p *plugin) run(args ...interface{}) (interface{}, error) { case sig := <-sigs: // Pass signals to the sub-process if c.Process != nil { - // nolint: gosec _ = c.Process.Signal(sig) } case <-ctx.Done(): diff --git a/random/random.go b/random/random.go index 742099d06..e3fd23906 100644 --- a/random/random.go +++ b/random/random.go @@ -15,7 +15,7 @@ const defaultSet = "-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstu // StringRE - Generate a random string that matches a given regular // expression. Defaults to "[a-zA-Z0-9_.-]" func StringRE(count int, match string) (r string, err error) { - var chars = []rune(defaultSet) + chars := []rune(defaultSet) if match != "" { chars, err = matchChars(match) if err != nil { diff --git a/regexp/regexp_test.go b/regexp/regexp_test.go index f1d1132f4..ddbe85f16 100644 --- a/regexp/regexp_test.go +++ b/regexp/regexp_test.go @@ -38,6 +38,7 @@ func TestFindAll(t *testing.T) { assert.EqualValues(t, d.expected, f) } } + func TestMatch(t *testing.T) { assert.True(t, Match(`^[a-z]+\[[0-9]+\]$`, "adam[23]")) assert.True(t, Match(`^[a-z]+\[[0-9]+\]$`, "eve[7]")) diff --git a/render.go b/render.go index b9e5d0bc1..7c9593e86 100644 --- a/render.go +++ b/render.go @@ -11,7 +11,6 @@ import ( "time" "github.com/hairyhenderson/gomplate/v4/data" - "github.com/hairyhenderson/gomplate/v4/funcs" //nolint:staticcheck "github.com/hairyhenderson/gomplate/v4/internal/config" ) @@ -210,27 +209,7 @@ func (t *Renderer) RenderTemplates(ctx context.Context, templates []Template) er func (t *Renderer) renderTemplatesWithData(ctx context.Context, templates []Template, tmplctx interface{}) error { // update funcs with the current context // only done here to ensure the context is properly set in func namespaces - f := template.FuncMap{} - addToMap(f, funcs.CreateDataFuncs(ctx, t.data)) - addToMap(f, funcs.CreateAWSFuncs(ctx)) - addToMap(f, funcs.CreateGCPFuncs(ctx)) - addToMap(f, funcs.CreateBase64Funcs(ctx)) - addToMap(f, funcs.CreateNetFuncs(ctx)) - addToMap(f, funcs.CreateReFuncs(ctx)) - addToMap(f, funcs.CreateStringFuncs(ctx)) - addToMap(f, funcs.CreateEnvFuncs(ctx)) - addToMap(f, funcs.CreateConvFuncs(ctx)) - addToMap(f, funcs.CreateTimeFuncs(ctx)) - addToMap(f, funcs.CreateMathFuncs(ctx)) - addToMap(f, funcs.CreateCryptoFuncs(ctx)) - addToMap(f, funcs.CreateFileFuncs(ctx)) - addToMap(f, funcs.CreateFilePathFuncs(ctx)) - addToMap(f, funcs.CreatePathFuncs(ctx)) - addToMap(f, funcs.CreateSockaddrFuncs(ctx)) - addToMap(f, funcs.CreateTestFuncs(ctx)) - addToMap(f, funcs.CreateCollFuncs(ctx)) - addToMap(f, funcs.CreateUUIDFuncs(ctx)) - addToMap(f, funcs.CreateRandomFuncs(ctx)) + f := CreateFuncs(ctx, t.data) // add user-defined funcs last so they override the built-in funcs addToMap(f, t.funcs) diff --git a/template.go b/template.go index 54095fddd..7aad0694f 100644 --- a/template.go +++ b/template.go @@ -162,7 +162,8 @@ func parseNestedTemplate(_ context.Context, fsys fs.FS, alias, fname string, tmp } // gatherTemplates - gather and prepare templates for rendering -// nolint: gocyclo +// +//nolint:gocyclo func gatherTemplates(ctx context.Context, cfg *config.Config, outFileNamer func(context.Context, string) (string, error)) ([]Template, error) { mode, modeOverride, err := cfg.GetMode() if err != nil { @@ -314,7 +315,7 @@ func fileToTemplate(ctx context.Context, cfg *config.Config, inFile, outFile str // open the output file - no need to close it, as it will be closed by the // caller later - target, err := openOutFile(ctx, outFile, 0755, mode, modeOverride, cfg.Stdout, cfg.SuppressEmpty) + target, err := openOutFile(ctx, outFile, 0o755, mode, modeOverride, cfg.Stdout, cfg.SuppressEmpty) if err != nil { return Template{}, fmt.Errorf("openOutFile: %w", err) } @@ -336,6 +337,8 @@ func fileToTemplate(ctx context.Context, cfg *config.Config, inFile, outFile str // // TODO: the 'suppressEmpty' behaviour should be always enabled, in the next // major release (v4.x). +// +//nolint:unparam // TODO: dirMode is always called with 0o755 - should either remove or make it configurable func openOutFile(ctx context.Context, filename string, dirMode, mode os.FileMode, modeOverride bool, stdout io.Writer, suppressEmpty bool) (out io.Writer, err error) { if suppressEmpty { out = iohelpers.NewEmptySkipper(func() (io.Writer, error) { diff --git a/template_test.go b/template_test.go index fd6a387a9..d21d693e1 100644 --- a/template_test.go +++ b/template_test.go @@ -40,11 +40,11 @@ func TestOpenOutFile(t *testing.T) { i, err := hackpadfs.Stat(fsys, "/tmp/foo") require.NoError(t, err) - assert.Equal(t, iohelpers.NormalizeFileMode(0644), i.Mode()) + assert.Equal(t, iohelpers.NormalizeFileMode(0o644), i.Mode()) out := &bytes.Buffer{} - f, err = openOutFile(ctx, "-", 0755, 0644, false, out, false) + f, err = openOutFile(ctx, "-", 0o755, 0o644, false, out, false) require.NoError(t, err) assert.Equal(t, cfg.Stdout, f) } @@ -116,14 +116,14 @@ func TestGatherTemplates(t *testing.T) { assert.Len(t, templates, 1) assert.Equal(t, "bar", templates[0].Text) assert.NotEqual(t, cfg.Stdout, templates[0].Writer) - // assert.Equal(t, os.FileMode(0600), templates[0].mode) + // assert.Equal(t, os.FileMode(0o600), templates[0].mode) _, err = templates[0].Writer.Write([]byte("hello world")) require.NoError(t, err) info, err = hackpadfs.Stat(fsys, "out") require.NoError(t, err) - assert.Equal(t, iohelpers.NormalizeFileMode(0600), info.Mode()) + assert.Equal(t, iohelpers.NormalizeFileMode(0o600), info.Mode()) hackpadfs.Remove(fsys, "out") cfg = &config.Config{ @@ -137,14 +137,14 @@ func TestGatherTemplates(t *testing.T) { assert.Len(t, templates, 1) assert.Equal(t, "bar", templates[0].Text) assert.NotEqual(t, cfg.Stdout, templates[0].Writer) - // assert.Equal(t, iohelpers.NormalizeFileMode(0755), templates[0].mode) + // assert.Equal(t, iohelpers.NormalizeFileMode(0o755), templates[0].mode) _, err = templates[0].Writer.Write([]byte("hello world")) require.NoError(t, err) info, err = hackpadfs.Stat(fsys, "out") require.NoError(t, err) - assert.Equal(t, iohelpers.NormalizeFileMode(0755), info.Mode()) + assert.Equal(t, iohelpers.NormalizeFileMode(0o755), info.Mode()) hackpadfs.Remove(fsys, "out") templates, err = gatherTemplates(ctx, &config.Config{ @@ -159,11 +159,11 @@ func TestGatherTemplates(t *testing.T) { func TestCreateOutFile(t *testing.T) { fsys, _ := mem.NewFS() - _ = hackpadfs.Mkdir(fsys, "in", 0755) + _ = hackpadfs.Mkdir(fsys, "in", 0o755) ctx := datafs.ContextWithFSProvider(context.Background(), datafs.WrappedFSProvider(fsys, "file")) - _, err := createOutFile(ctx, "in", 0755, 0644, false) + _, err := createOutFile(ctx, "in", 0o755, 0o644, false) assert.Error(t, err) assert.IsType(t, &fs.PathError{}, err) } diff --git a/vault/testutils.go b/vault/testutils.go index 2db9f78f0..479a669c8 100644 --- a/vault/testutils.go +++ b/vault/testutils.go @@ -13,7 +13,6 @@ import ( func MockServer(code int, body string) (*httptest.Server, *Vault) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(code) - // nolint: errcheck fmt.Fprintln(w, body) })) @@ -27,7 +26,7 @@ func MockServer(code int, body string) (*httptest.Server, *Vault) { Address: server.URL, HttpClient: httpClient, } - // nolint: gosec + c, _ := api.NewClient(config) return server, &Vault{c} } diff --git a/version/gen/vgen.go b/version/gen/vgen.go index 25df7e1e1..4528b2d74 100644 --- a/version/gen/vgen.go +++ b/version/gen/vgen.go @@ -22,10 +22,7 @@ func main() { log.Fatal(err) } - ver, err := version(descVer, latest) - if err != nil { - log.Fatal(err) - } + ver := version(descVer, latest) fmt.Println(ver.String()) } @@ -44,7 +41,7 @@ func describedVersion() (*semver.Version, error) { return ver, nil } -func version(descVer, latest *semver.Version) (*semver.Version, error) { +func version(descVer, latest *semver.Version) *semver.Version { ver := *descVer if ver.Prerelease() != "" { ver = ver.IncPatch().IncPatch() @@ -57,7 +54,7 @@ func version(descVer, latest *semver.Version) (*semver.Version, error) { // if we're on a release tag already, we're done if descVer.Equal(&ver) { - return descVer, nil + return descVer } // If 'latest' is greater than 'ver', we need to skip to the next patch. @@ -76,7 +73,7 @@ func version(descVer, latest *semver.Version) (*semver.Version, error) { ver = v } - return &ver, nil + return &ver } func latestTag() (*semver.Version, error) { diff --git a/version/gen/vgen_test.go b/version/gen/vgen_test.go index a9c360e69..002475a20 100644 --- a/version/gen/vgen_test.go +++ b/version/gen/vgen_test.go @@ -24,8 +24,7 @@ func TestVersion(t *testing.T) { l = semver.MustParse(td.latest) } - ver, err := version(semver.MustParse(td.desc), l) - require.NoError(t, err) + ver := version(semver.MustParse(td.desc), l) require.Equal(t, td.expected, ver.String()) } }