diff --git a/.github/actions/lint-terraform-svchost/action.yml b/.github/actions/lint-terraform-svchost/action.yml new file mode 100644 index 0000000..4edadd6 --- /dev/null +++ b/.github/actions/lint-terraform-svchost/action.yml @@ -0,0 +1,25 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +name: Lint +description: Lints terraform-svchost +runs: + using: composite + steps: + - name: Setup Go Environment + uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 + with: + go-version-file: "go.mod" + cache: true + + - run: make fmtcheck + shell: bash + + - name: Install golangci-lint + run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/0b5709648c8ba9780e821faf16c5c2bb3262ce3e/install.sh | sh -s -- -b $(go env GOPATH)/bin $GOLANGCILINT_VERSION + shell: bash + env: + GOLANGCILINT_VERSION: v1.55.2 + + - run: make lint + shell: bash diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 02b6590..bb09c20 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,12 +9,19 @@ on: - main jobs: + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + - uses: ./.github/actions/lint-terraform-svchost + copywrite: name: Run Header Copyright runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Install Copywrite id: install @@ -31,7 +38,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Set up Go uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0 diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..e1ff62d --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,62 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +run: + timeout: 5m +linters: + # This set of linters are enabled by default: deadcode, errcheck, gosimple, govet, ineffasign, staticcheck, struccheck, typecheck, unused, varcheck + enable: + # List of all linters: https://golangci-lint.run/usage/linters/ + - whitespace #https://github.com/ultraware/whitespace + # - noctx #https://github.com/sonatard/noctx + - nilerr #https://github.com/gostaticanalysis/nilerr + - nestif #https://github.com/nakabonne/nestif + - exportloopref #https://github.com/kyoh86/exportloopref + - bodyclose #https://github.com/timakin/bodyclose + - goconst #https://github.com/jgautheron/goconst + - gofmt + - errcheck #https://github.com/kisielk/errcheck + - stylecheck #https://github.com/dominikh/go-tools/tree/master/stylecheck + - revive #golint is deprecated and golangci-lint recommends to use revive instead https://github.com/mgechev/revive + #other deprecated lint libraries: maligned, scopelint, interfacer + - gocritic #https://github.com/go-critic/go-critic + - unparam #https://github.com/mvdan/unparam + - misspell #https://github.com/client9/misspell +issues: + exclude-rules: + - path: _test\.go + linters: + - unused + - deadcode + - unparam + - errcheck +linters-settings: + errcheck: + # https://github.com/kisielk/errcheck#excluding-functions + check-type-assertions: true + check-blank: true + goconst: + min-len: 20 + min-occurrences: 5 + ignore-calls: false + ignore-tests: true + gocritic: + enabled-tags: + - diagnostic + - opinionated + - performance + disabled-checks: + - unnamedResult + - hugeParam + - singleCaseSwitch + - ifElseChain + - sloppyTestFuncName + revive: + # see https://github.com/mgechev/revive#available-rules for details. + ignore-generated-header: false #recommended in their configuration + severity: warning + rules: + - name: indent-error-flow #Prevents redundant else statements + severity: warning + - name: useless-break + severity: warning diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a08037a --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +TEST?=$$(go list ./... |grep -v 'vendor') +GOFMT_FILES?=$$(find . -name '*.go' |grep -v vendor) +PKG_NAME=tfe + +fmt: + gofmt -w $(GOFMT_FILES) + +lint: + @golangci-lint run ; if [ $$? -ne 0 ]; then \ + echo ""; \ + echo "golangci-lint found some code style issues."; \ + exit 1; \ + fi + +fmtcheck: + @sh -c "'$(CURDIR)/scripts/gofmtcheck.sh'" + +.PHONY: fmt lint fmtcheck + diff --git a/auth/helper_program.go b/auth/helper_program.go index 8c4591d..dd9df3e 100644 --- a/auth/helper_program.go +++ b/auth/helper_program.go @@ -9,9 +9,8 @@ import ( "os/exec" "path/filepath" + svchost "github.com/hashicorp/terraform-svchost" ctyjson "github.com/zclconf/go-cty/cty/json" - - "github.com/hashicorp/terraform-svchost" ) type helperProgramCredentialsSource struct { @@ -49,8 +48,7 @@ func HelperProgramCredentialsSource(executable string, args ...string) Credentia func (s *helperProgramCredentialsSource) ForHost(host svchost.Hostname) (HostCredentials, error) { args := make([]string, len(s.args), len(s.args)+2) copy(args, s.args) - args = append(args, "get") - args = append(args, string(host)) + args = append(args, "get", string(host)) outBuf := bytes.Buffer{} errBuf := bytes.Buffer{} @@ -86,8 +84,7 @@ func (s *helperProgramCredentialsSource) ForHost(host svchost.Hostname) (HostCre func (s *helperProgramCredentialsSource) StoreForHost(host svchost.Hostname, credentials HostCredentialsWritable) error { args := make([]string, len(s.args), len(s.args)+2) copy(args, s.args) - args = append(args, "store") - args = append(args, string(host)) + args = append(args, "store", string(host)) toStore := credentials.ToStore() toStoreRaw, err := ctyjson.Marshal(toStore, toStore.Type()) @@ -123,8 +120,7 @@ func (s *helperProgramCredentialsSource) StoreForHost(host svchost.Hostname, cre func (s *helperProgramCredentialsSource) ForgetForHost(host svchost.Hostname) error { args := make([]string, len(s.args), len(s.args)+2) copy(args, s.args) - args = append(args, "forget") - args = append(args, string(host)) + args = append(args, "forget", string(host)) errBuf := bytes.Buffer{} diff --git a/auth/helper_program_test.go b/auth/helper_program_test.go index 8d2849d..adbf305 100644 --- a/auth/helper_program_test.go +++ b/auth/helper_program_test.go @@ -7,7 +7,7 @@ import ( "path/filepath" "testing" - "github.com/hashicorp/terraform-svchost" + svchost "github.com/hashicorp/terraform-svchost" ) func TestHelperProgramCredentialsSource(t *testing.T) { @@ -16,7 +16,7 @@ func TestHelperProgramCredentialsSource(t *testing.T) { t.Fatal(err) } - program := filepath.Join(wd, "testdata/test-helper") + program := filepath.Join(wd, "testdata", "test-helper") t.Logf("testing with helper at %s", program) src := HelperProgramCredentialsSource(program) diff --git a/auth/static_test.go b/auth/static_test.go index 9675e2f..567cc16 100644 --- a/auth/static_test.go +++ b/auth/static_test.go @@ -5,12 +5,12 @@ package auth import ( "testing" - "github.com/hashicorp/terraform-svchost" + svchost "github.com/hashicorp/terraform-svchost" ) func TestStaticCredentialsSource(t *testing.T) { src := StaticCredentialsSource(map[svchost.Hostname]map[string]interface{}{ - svchost.Hostname("example.com"): map[string]interface{}{ + svchost.Hostname("example.com"): { "token": "abc123", }, }) diff --git a/disco/disco.go b/disco/disco.go index 9a535d5..0d4ef33 100644 --- a/disco/disco.go +++ b/disco/disco.go @@ -38,7 +38,7 @@ const ( ) // httpTransport is overridden during tests, to skip TLS verification. -var httpTransport = defaultHttpTransport() +var httpTransport = defaultHTTPTransport() // Disco is the main type in this package, which allows discovery on given // hostnames and caches the results by hostname to avoid repeated requests @@ -62,8 +62,8 @@ type ErrServiceDiscoveryNetworkRequest struct { } func (e ErrServiceDiscoveryNetworkRequest) Error() string { - wrapped_error := fmt.Errorf("failed to request discovery document: %w", e.err) - return wrapped_error.Error() + wrappedError := fmt.Errorf("failed to request discovery document: %w", e.err) + return wrappedError.Error() } // New returns a new initialized discovery object. diff --git a/disco/disco_test.go b/disco/disco_test.go index ef7e4d6..fb8bb08 100644 --- a/disco/disco_test.go +++ b/disco/disco_test.go @@ -29,7 +29,7 @@ func TestMain(m *testing.M) { func TestDiscover(t *testing.T) { t.Run("happy path", func(t *testing.T) { - portStr, close := testServer(func(w http.ResponseWriter, r *http.Request) { + portStr, cleanup := testServer(func(w http.ResponseWriter, r *http.Request) { resp := []byte(` { "thingy.v1": "http://example.com/foo", @@ -40,7 +40,7 @@ func TestDiscover(t *testing.T) { w.Header().Add("Content-Length", strconv.Itoa(len(resp))) w.Write(resp) }) - defer close() + defer cleanup() givenHost := "localhost" + portStr host, err := svchost.ForComparison(givenHost) @@ -66,7 +66,7 @@ func TestDiscover(t *testing.T) { } }) t.Run("chunked encoding", func(t *testing.T) { - portStr, close := testServer(func(w http.ResponseWriter, r *http.Request) { + portStr, cleanup := testServer(func(w http.ResponseWriter, r *http.Request) { resp := []byte(` { "thingy.v1": "http://example.com/foo", @@ -82,7 +82,7 @@ func TestDiscover(t *testing.T) { w.Write(resp[5:]) w.(http.Flusher).Flush() }) - defer close() + defer cleanup() givenHost := "localhost" + portStr host, err := svchost.ForComparison(givenHost) @@ -109,14 +109,14 @@ func TestDiscover(t *testing.T) { }) t.Run("with credentials", func(t *testing.T) { var authHeaderText string - portStr, close := testServer(func(w http.ResponseWriter, r *http.Request) { + portStr, cleanup := testServer(func(w http.ResponseWriter, r *http.Request) { resp := []byte(`{}`) authHeaderText = r.Header.Get("Authorization") w.Header().Add("Content-Type", "application/json") w.Header().Add("Content-Length", strconv.Itoa(len(resp))) w.Write(resp) }) - defer close() + defer cleanup() givenHost := "localhost" + portStr host, err := svchost.ForComparison(givenHost) @@ -126,7 +126,7 @@ func TestDiscover(t *testing.T) { d := New() d.SetCredentialsSource(auth.StaticCredentialsSource(map[svchost.Hostname]map[string]interface{}{ - host: map[string]interface{}{ + host: { "token": "abc123", }, })) @@ -180,12 +180,12 @@ func TestDiscover(t *testing.T) { } }) t.Run("not JSON", func(t *testing.T) { - portStr, close := testServer(func(w http.ResponseWriter, r *http.Request) { + portStr, cleanup := testServer(func(w http.ResponseWriter, r *http.Request) { resp := []byte(`{"thingy.v1": "http://example.com/foo"}`) w.Header().Add("Content-Type", "application/octet-stream") w.Write(resp) }) - defer close() + defer cleanup() givenHost := "localhost" + portStr host, err := svchost.ForComparison(givenHost) @@ -205,12 +205,12 @@ func TestDiscover(t *testing.T) { } }) t.Run("malformed JSON", func(t *testing.T) { - portStr, close := testServer(func(w http.ResponseWriter, r *http.Request) { + portStr, cleanup := testServer(func(w http.ResponseWriter, r *http.Request) { resp := []byte(`{"thingy.v1": "htt`) // truncated, for example... w.Header().Add("Content-Type", "application/json") w.Write(resp) }) - defer close() + defer cleanup() givenHost := "localhost" + portStr host, err := svchost.ForComparison(givenHost) @@ -234,12 +234,12 @@ func TestDiscover(t *testing.T) { // MIME type, but some servers have a weird tendency to just add // "charset" to everything, so we'll make sure we ignore it successfully. // (JSON uses content sniffing for encoding detection, not media type params.) - portStr, close := testServer(func(w http.ResponseWriter, r *http.Request) { + portStr, cleanup := testServer(func(w http.ResponseWriter, r *http.Request) { resp := []byte(`{"thingy.v1": "http://example.com/foo"}`) w.Header().Add("Content-Type", "application/json; charset=latin-1") w.Write(resp) }) - defer close() + defer cleanup() givenHost := "localhost" + portStr host, err := svchost.ForComparison(givenHost) @@ -258,10 +258,10 @@ func TestDiscover(t *testing.T) { } }) t.Run("no discovery doc", func(t *testing.T) { - portStr, close := testServer(func(w http.ResponseWriter, r *http.Request) { + portStr, cleanup := testServer(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(404) }) - defer close() + defer cleanup() givenHost := "localhost" + portStr host, err := svchost.ForComparison(givenHost) @@ -284,10 +284,10 @@ func TestDiscover(t *testing.T) { t.Run("discovery error", func(t *testing.T) { // Make a channel and then ignore messages to simulate a Client.Timeout donec := make(chan bool, 1) - portStr, close := testServer(func(w http.ResponseWriter, r *http.Request) { + portStr, cleanup := testServer(func(w http.ResponseWriter, r *http.Request) { <-donec }) - defer close() + defer cleanup() defer func() { donec <- true }() givenHost := "localhost" + portStr @@ -327,7 +327,7 @@ func TestDiscover(t *testing.T) { }) portStr2, close2 := testServer(func(w http.ResponseWriter, r *http.Request) { // This server is the one that redirects. - http.Redirect(w, r, "https://localhost"+portStr1+"/.well-known/terraform.json", 302) + http.Redirect(w, r, "https://localhost"+portStr1+"/.well-known/terraform.json", http.StatusFound) }) defer close1() defer close2() @@ -362,13 +362,12 @@ func TestDiscover(t *testing.T) { if gotBaseURL != wantBaseURL { t.Errorf("incorrect base url %s; want %s", gotBaseURL, wantBaseURL) } - }) t.Run("alias", func(t *testing.T) { // The server will listen on localhost and we will expect this response // by requesting discovery on the alias. - portStr, close := testServer(func(w http.ResponseWriter, r *http.Request) { + portStr, cleanup := testServer(func(w http.ResponseWriter, r *http.Request) { resp := []byte(` { "thingy.v1": "http://example.com/foo" @@ -378,7 +377,7 @@ func TestDiscover(t *testing.T) { w.Header().Add("Content-Length", strconv.Itoa(len(resp))) w.Write(resp) }) - defer close() + defer cleanup() target, err := svchost.ForComparison("localhost" + portStr) if err != nil { @@ -434,7 +433,7 @@ func TestDiscover(t *testing.T) { }) } -func testServer(h func(w http.ResponseWriter, r *http.Request)) (portStr string, close func()) { +func testServer(h func(w http.ResponseWriter, r *http.Request)) (portStr string, cleanup func()) { server := httptest.NewTLSServer(http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { // Test server always returns 404 if the URL isn't what we expect @@ -456,9 +455,9 @@ func testServer(h func(w http.ResponseWriter, r *http.Request)) (portStr string, portStr = ":" + portStr } - close = func() { + cleanup = func() { server.Close() } - return portStr, close + return portStr, cleanup } diff --git a/disco/host.go b/disco/host.go index eee5250..93d3969 100644 --- a/disco/host.go +++ b/disco/host.go @@ -114,7 +114,7 @@ func (h *Host) ServiceURL(id string) (*url.URL, error) { u, err := h.parseURL(urlStr) if err != nil { - return nil, fmt.Errorf("Failed to parse service URL: %v", err) + return nil, fmt.Errorf("failed to parse service URL: %v", err) } return u, nil @@ -164,10 +164,11 @@ func (h *Host) ServiceOAuthClient(id string) (*OAuthClient, error) { default: // Debug message because raw Go types don't belong in our UI. log.Printf("[DEBUG] The definition for %s has Go type %T", id, h.services[id]) - return nil, fmt.Errorf("Service %s must be declared with an object value in the service discovery document", id) + return nil, fmt.Errorf("service %s must be declared with an object value in the service discovery document", id) } var grantTypes OAuthGrantTypeSet + //nolint:nestif if rawGTs, ok := raw["grant_types"]; ok { if gts, ok := rawGTs.([]interface{}); ok { var kws []string @@ -182,7 +183,7 @@ func (h *Host) ServiceOAuthClient(id string) (*OAuthClient, error) { } grantTypes = NewOAuthGrantTypeSet(kws...) } else { - return nil, fmt.Errorf("Service %s is defined with invalid grant_types property: must be an array of grant type strings", id) + return nil, fmt.Errorf("service %s is defined with invalid grant_types property: must be an array of grant type strings", id) } } else { grantTypes = NewOAuthGrantTypeSet("authz_code") @@ -194,35 +195,32 @@ func (h *Host) ServiceOAuthClient(id string) (*OAuthClient, error) { if clientIDStr, ok := raw["client"].(string); ok { ret.ID = clientIDStr } else { - return nil, fmt.Errorf("Service %s definition is missing required property \"client\"", id) + return nil, fmt.Errorf("service %s definition is missing required property \"client\"", id) } if urlStr, ok := raw["authz"].(string); ok { u, err := h.parseURL(urlStr) if err != nil { - return nil, fmt.Errorf("Failed to parse authorization URL: %v", err) + return nil, fmt.Errorf("failed to parse authorization URL: %v", err) } ret.AuthorizationURL = u - } else { - if grantTypes.RequiresAuthorizationEndpoint() { - return nil, fmt.Errorf("Service %s definition is missing required property \"authz\"", id) - } + } else if grantTypes.RequiresAuthorizationEndpoint() { + return nil, fmt.Errorf("service %s definition is missing required property \"authz\"", id) } if urlStr, ok := raw["token"].(string); ok { u, err := h.parseURL(urlStr) if err != nil { - return nil, fmt.Errorf("Failed to parse token URL: %v", err) + return nil, fmt.Errorf("failed to parse token URL: %v", err) } ret.TokenURL = u - } else { - if grantTypes.RequiresTokenEndpoint() { - return nil, fmt.Errorf("Service %s definition is missing required property \"token\"", id) - } + } else if grantTypes.RequiresTokenEndpoint() { + return nil, fmt.Errorf("service %s definition is missing required property \"token\"", id) } + //nolint:nestif if portsRaw, ok := raw["ports"].([]interface{}); ok { if len(portsRaw) != 2 { - return nil, fmt.Errorf("Invalid \"ports\" definition for service %s: must be a two-element array", id) + return nil, fmt.Errorf("invalid \"ports\" definition for service %s: must be a two-element array", id) } - invalidPortsErr := fmt.Errorf("Invalid \"ports\" definition for service %s: both ports must be whole numbers between 1024 and 65535", id) + invalidPortsErr := fmt.Errorf("invalid \"ports\" definition for service %s: both ports must be whole numbers between 1024 and 65535", id) ports := make([]uint16, 2) for i := range ports { switch v := portsRaw[i].(type) { @@ -247,7 +245,7 @@ func (h *Host) ServiceOAuthClient(id string) (*OAuthClient, error) { } } if ports[1] < ports[0] { - return nil, fmt.Errorf("Invalid \"ports\" definition for service %s: minimum port cannot be greater than maximum port", id) + return nil, fmt.Errorf("invalid \"ports\" definition for service %s: minimum port cannot be greater than maximum port", id) } ret.MinPort = ports[0] ret.MaxPort = ports[1] @@ -262,7 +260,7 @@ func (h *Host) ServiceOAuthClient(id string) (*OAuthClient, error) { for _, scopeI := range scopesRaw { scope, ok := scopeI.(string) if !ok { - return nil, fmt.Errorf("Invalid \"scopes\" for service %s: all scopes must be strings", id) + return nil, fmt.Errorf("invalid \"scopes\" for service %s: all scopes must be strings", id) } scopes = append(scopes, scope) } @@ -303,7 +301,7 @@ func (h *Host) parseURL(urlStr string) (*url.URL, error) { // that service are returned. // // When the requested version is not provided but the service is, we will -// search for all alternative versions. If mutliple alternative versions +// search for all alternative versions. If multiple alternative versions // are found, the contrains of the latest available version are returned. // // When a service is not provided at all an error will be returned instead. @@ -334,6 +332,7 @@ func (h *Host) VersionConstraints(id, product string) (*Constraints, error) { } // Check if we have an exact (service and version) match. + //nolint:nestif if _, ok := h.services[id].(string); !ok { // If we don't have an exact match, we search for all matching // services and then use the service ID of the latest version. @@ -381,7 +380,7 @@ func (h *Host) VersionConstraints(id, product string) (*Constraints, error) { // Create a new request. req, err := http.NewRequest("GET", u.String(), nil) if err != nil { - return nil, fmt.Errorf("Failed to create version constraints request: %v", err) + return nil, fmt.Errorf("failed to create version constraints request: %v", err) } req.Header.Set("Accept", "application/json") @@ -389,7 +388,7 @@ func (h *Host) VersionConstraints(id, product string) (*Constraints, error) { resp, err := client.Do(req) if err != nil { - return nil, fmt.Errorf("Failed to request version constraints: %v", err) + return nil, fmt.Errorf("failed to request version constraints: %v", err) } defer resp.Body.Close() @@ -398,7 +397,7 @@ func (h *Host) VersionConstraints(id, product string) (*Constraints, error) { } if resp.StatusCode != 200 { - return nil, fmt.Errorf("Failed to request version constraints: %s", resp.Status) + return nil, fmt.Errorf("failed to request version constraints: %s", resp.Status) } // Parse the constraints from the response body. @@ -413,13 +412,13 @@ func (h *Host) VersionConstraints(id, product string) (*Constraints, error) { func parseServiceID(id string) (string, *version.Version, error) { parts := strings.SplitN(id, ".", 2) if len(parts) != 2 { - return "", nil, fmt.Errorf("Invalid service ID format (i.e. service.vN): %s", id) + return "", nil, fmt.Errorf("invalid service ID format (i.e. service.vN): %s", id) } - version, err := version.NewVersion(parts[1]) + parsedVersion, err := version.NewVersion(parts[1]) if err != nil { - return "", nil, fmt.Errorf("Invalid service version: %v", err) + return "", nil, fmt.Errorf("invalid service version: %v", err) } - return parts[0], version, nil + return parts[0], parsedVersion, nil } diff --git a/disco/host_test.go b/disco/host_test.go index 795aadb..d5b011d 100644 --- a/disco/host_test.go +++ b/disco/host_test.go @@ -48,20 +48,20 @@ func TestHostServiceURL(t *testing.T) { {"withfragment.v1", "http://example.org/", ""}, {"querystring.v1", "https://example.net/baz?foo=bar", ""}, {"nothttp.v1", "", "unsupported scheme"}, - {"invalid.v1", "", "Failed to parse service URL"}, + {"invalid.v1", "", "failed to parse service URL"}, } for _, test := range tests { t.Run(test.ID, func(t *testing.T) { - url, err := host.ServiceURL(test.ID) + serviceURL, err := host.ServiceURL(test.ID) if (err != nil || test.err != "") && (err == nil || !strings.Contains(err.Error(), test.err)) { t.Fatalf("unexpected service URL error: %s", err) } var got string - if url != nil { - got = url.String() + if serviceURL != nil { + got = serviceURL.String() } else { got = "" } @@ -212,17 +212,17 @@ func TestHostServiceOAuthClient(t *testing.T) { { "invalidports.v1", nil, - `Invalid "ports" definition for service invalidports.v1: both ports must be whole numbers between 1024 and 65535`, + `invalid "ports" definition for service invalidports.v1: both ports must be whole numbers between 1024 and 65535`, }, { "missingauthz.v1", nil, - `Service missingauthz.v1 definition is missing required property "authz"`, + `service missingauthz.v1 definition is missing required property "authz"`, }, { "missingtoken.v1", nil, - `Service missingtoken.v1 definition is missing required property "token"`, + `service missingtoken.v1 definition is missing required property "token"`, }, { "passwordmissingauthz.v1", @@ -298,17 +298,17 @@ func TestHostServiceOAuthClient(t *testing.T) { { "nothttp.v1", nil, - "Failed to parse authorization URL: unsupported scheme ftp", + "failed to parse authorization URL: unsupported scheme ftp", }, { "invalidauthz.v1", nil, - "Failed to parse authorization URL: parse \"***not A URL at all!:/<@@@@>***\": first path segment in URL cannot contain colon", + "failed to parse authorization URL: parse \"***not A URL at all!:/<@@@@>***\": first path segment in URL cannot contain colon", }, { "invalidtoken.v1", nil, - "Failed to parse token URL: parse \"***not A URL at all!:/<@@@@>***\": first path segment in URL cannot contain colon", + "failed to parse token URL: parse \"***not A URL at all!:/<@@@@>***\": first path segment in URL cannot contain colon", }, { "scopesincluded.v1", @@ -338,7 +338,7 @@ func TestHostServiceOAuthClient(t *testing.T) { { "scopesbad.v1", nil, - `Invalid "scopes" for service scopesbad.v1: all scopes must be strings`, + `invalid "scopes" for service scopesbad.v1: all scopes must be strings`, }, } @@ -361,7 +361,7 @@ func TestVersionConstrains(t *testing.T) { baseURL, _ := url.Parse("https://example.com/disco/foo.json") t.Run("exact service version is provided", func(t *testing.T) { - portStr, close := testVersionsServer(func(w http.ResponseWriter, r *http.Request) { + portStr, cleanup := testVersionsServer(func(w http.ResponseWriter, r *http.Request) { resp := []byte(` { "service": "%s", @@ -378,7 +378,7 @@ func TestVersionConstrains(t *testing.T) { w.Header().Add("Content-Length", strconv.Itoa(len(resp))) w.Write(resp) }) - defer close() + defer cleanup() host := Host{ discoURL: baseURL, @@ -409,7 +409,7 @@ func TestVersionConstrains(t *testing.T) { }) t.Run("service provided with different versions", func(t *testing.T) { - portStr, close := testVersionsServer(func(w http.ResponseWriter, r *http.Request) { + portStr, cleanup := testVersionsServer(func(w http.ResponseWriter, r *http.Request) { resp := []byte(` { "service": "%s", @@ -426,7 +426,7 @@ func TestVersionConstrains(t *testing.T) { w.Header().Add("Content-Length", strconv.Itoa(len(resp))) w.Write(resp) }) - defer close() + defer cleanup() host := Host{ discoURL: baseURL, @@ -473,8 +473,8 @@ func TestVersionConstrains(t *testing.T) { }) t.Run("versions service returns a 404", func(t *testing.T) { - portStr, close := testVersionsServer(nil) - defer close() + portStr, cleanup := testVersionsServer(nil) + defer cleanup() host := Host{ discoURL: baseURL, @@ -548,7 +548,7 @@ func TestVersionConstrains(t *testing.T) { }) } -func testVersionsServer(h func(w http.ResponseWriter, r *http.Request)) (portStr string, close func()) { +func testVersionsServer(h func(w http.ResponseWriter, r *http.Request)) (portStr string, cleanup func()) { server := httptest.NewTLSServer(http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { // Test server always returns 404 if the URL isn't what we expect @@ -570,9 +570,9 @@ func testVersionsServer(h func(w http.ResponseWriter, r *http.Request)) (portStr portStr = ":" + portStr } - close = func() { + cleanup = func() { server.Close() } - return portStr, close + return portStr, cleanup } diff --git a/disco/http_transport.go b/disco/http_transport.go index f98274d..649e029 100644 --- a/disco/http_transport.go +++ b/disco/http_transport.go @@ -10,7 +10,7 @@ import ( const DefaultUserAgent = "terraform-svchost/1.0" -func defaultHttpTransport() http.RoundTripper { +func defaultHTTPTransport() http.RoundTripper { t := cleanhttp.DefaultPooledTransport() return &userAgentRoundTripper{ innerRt: t, diff --git a/label_iter.go b/label_iter.go index eb87568..db1a362 100644 --- a/label_iter.go +++ b/label_iter.go @@ -19,23 +19,10 @@ type labelIter struct { i int } -func (l *labelIter) reset() { - l.curStart = 0 - l.curEnd = 0 - l.i = 0 -} - func (l *labelIter) done() bool { return l.curStart >= len(l.orig) } -func (l *labelIter) result() string { - if l.slice != nil { - return strings.Join(l.slice, ".") - } - return l.orig -} - func (l *labelIter) label() string { if l.slice != nil { return l.slice[l.i] @@ -62,10 +49,3 @@ func (l *labelIter) next() { } } } - -func (l *labelIter) set(s string) { - if l.slice == nil { - l.slice = strings.Split(l.orig, ".") - } - l.slice[l.i] = s -} diff --git a/scripts/gofmtcheck.sh b/scripts/gofmtcheck.sh new file mode 100755 index 0000000..ea1c15f --- /dev/null +++ b/scripts/gofmtcheck.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +# Check gofmt +gofmt_files=$(gofmt -l `find . -name '*.go' | grep -v vendor`) +if [[ -n ${gofmt_files} ]]; then + echo 'gofmt needs running on the following files:' + echo "${gofmt_files}" + echo "You can use the command: \`make fmt\` to reformat code." + exit 1 +fi + +exit 0 diff --git a/svchost.go b/svchost.go index 45a7029..6139637 100644 --- a/svchost.go +++ b/svchost.go @@ -58,6 +58,7 @@ func ForDisplay(given string) string { if colonPos := strings.Index(given, ":"); colonPos != -1 { given, portPortion = given[:colonPos], given[colonPos:] } + //nolint:errcheck portPortion, _ = normalizePortPortion(portPortion) ascii, err := displayProfile.ToASCII(given)