Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 7 additions & 21 deletions .github/workflows/unit.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
on: [push, pull_request]
name: Unit Testing
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
Expand All @@ -9,33 +9,19 @@ jobs:
go-version:
- "1.22"

env:
GO111MODULE: "on"

steps:
- name: Checkout source
uses: actions/checkout@v5

- name: Setup Go ${{ matrix.go-version }}
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}

- uses: actions/checkout@v5

- name: Setup environment
- name: Run linters
run: |
# Changing into a different directory to avoid polluting go.sum with "go get"
cd "$(mktemp -d)"
go mod init unit_tests

go install golang.org/x/tools/cmd/goimports@latest

- name: Run go vet
run: |
go vet ./...
make lint

- name: Run unit tests
run: |
go test -v ./...

- name: Check for formatting
run:
./script/format
make unit
30 changes: 30 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
version: "2"
linters:
default: none
enable:
- errcheck
- govet
- staticcheck
- unparam
- unused
exclusions:
generated: lax
presets:
- comments
- common-false-positives
- legacy
- std-error-handling
paths:
- third_party$
- builtin$
- examples$
formatters:
enable:
- gofmt
- goimports
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$
43 changes: 43 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
undefine GOFLAGS

GOLANGCI_LINT_VERSION?=v2.1.6
GOTESTSUM_VERSION?=v1.12.2
GO_TEST?=go run gotest.tools/gotestsum@$(GOTESTSUM_VERSION) --format testname --
TIMEOUT := "60m"

ifeq ($(shell command -v podman 2> /dev/null),)
RUNNER=docker
else
RUNNER=podman
endif

# if the golangci-lint steps fails with one of the following error messages:
#
# directory prefix . does not contain main module or its selected dependencies
#
# failed to initialize build cache at /root/.cache/golangci-lint: mkdir /root/.cache/golangci-lint: permission denied
#
# you probably have to fix the SELinux security context for root directory plus your cache
#
# chcon -Rt svirt_sandbox_file_t .
# chcon -Rt svirt_sandbox_file_t ~/.cache/golangci-lint
lint:
mkdir -p ~/.cache/golangci-lint/$(GOLANGCI_LINT_VERSION)
$(RUNNER) run -t --rm \
-v $(shell pwd):/app \
-v ~/.cache/golangci-lint/$(GOLANGCI_LINT_VERSION):/root/.cache \
-w /app \
golangci/golangci-lint:$(GOLANGCI_LINT_VERSION) golangci-lint run -v --max-same-issues 50
.PHONY: lint

format:
gofmt -w -s $(shell pwd)
.PHONY: format

unit:
$(GO_TEST) -shuffle on ./...
.PHONY: unit

coverage:
$(GO_TEST) -shuffle on -covermode count -coverprofile cover.out -coverpkg=./... ./...
.PHONY: coverage
45 changes: 21 additions & 24 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"sort"
Expand All @@ -19,22 +18,22 @@ import (

// Logger is an interface representing the Logger struct
type Logger interface {
Printf(format string, args ...interface{})
Printf(format string, args ...any)
}

// DefaultLogger is a default struct, which satisfies the Logger interface
type DefaultLogger struct{}

// Printf is a default Printf method
func (DefaultLogger) Printf(format string, args ...interface{}) {
func (DefaultLogger) Printf(format string, args ...any) {
log.Printf("[DEBUG] "+format, args...)
}

// noopLogger is a default noop logger satisfies the Logger interface
type noopLogger struct{}

// Printf is a default noop method
func (noopLogger) Printf(format string, args ...interface{}) {}
func (noopLogger) Printf(format string, args ...any) {}

// RoundTripper satisfies the http.RoundTripper interface and is used to
// customize the default http client RoundTripper
Expand Down Expand Up @@ -101,9 +100,7 @@ func (rt *RoundTripper) SetHeaders(headers http.Header) {
newHeaders := make(http.Header, len(headers))
for k, v := range headers {
s := make([]string, len(v))
for i, v := range v {
s[i] = v
}
copy(s, v)
newHeaders[k] = s
}

Expand Down Expand Up @@ -181,7 +178,7 @@ func (rt *RoundTripper) RoundTrip(request *http.Request) (*http.Response, error)
// this is concurrency safe
ort := rt.Rt
if ort == nil {
return nil, fmt.Errorf("Rt RoundTripper is nil, aborting")
return nil, fmt.Errorf("Rt RoundTripper is nil, aborting") //nolint
}
response, err := ort.RoundTrip(request)

Expand Down Expand Up @@ -232,7 +229,7 @@ func (rt *RoundTripper) logRequest(original io.ReadCloser, contentType string) (
}
rt.log().Printf("OpenStack Request Body: %s", debugInfo)

return ioutil.NopCloser(strings.NewReader(bs.String())), nil
return io.NopCloser(strings.NewReader(bs.String())), nil
}

rt.log().Printf("Not logging because OpenStack request body isn't JSON")
Expand All @@ -259,7 +256,7 @@ func (rt *RoundTripper) logResponse(original io.ReadCloser, contentType string)
rt.log().Printf("OpenStack Response Body: %s", debugInfo)
}

return ioutil.NopCloser(strings.NewReader(bs.String())), nil
return io.NopCloser(strings.NewReader(bs.String())), nil
}

rt.log().Printf("Not logging because OpenStack response body isn't JSON")
Expand Down Expand Up @@ -288,14 +285,14 @@ func (rt *RoundTripper) log() Logger {
// FormatJSON is a default function to pretty-format a JSON body.
// It will also mask known fields which contain sensitive information.
func FormatJSON(raw []byte) (string, error) {
var rawData interface{}
var rawData any

err := json.Unmarshal(raw, &rawData)
if err != nil {
return string(raw), fmt.Errorf("unable to parse OpenStack JSON: %s", err)
}

data, ok := rawData.(map[string]interface{})
data, ok := rawData.(map[string]any)
if !ok {
pretty, err := json.MarshalIndent(rawData, "", " ")
if err != nil {
Expand All @@ -306,32 +303,32 @@ func FormatJSON(raw []byte) (string, error) {
}

// Mask known password fields
if v, ok := data["auth"].(map[string]interface{}); ok {
if v, ok := data["auth"].(map[string]any); ok {
// v2 auth methods
if v, ok := v["passwordCredentials"].(map[string]interface{}); ok {
if v, ok := v["passwordCredentials"].(map[string]any); ok {
v["password"] = "***"
}
if v, ok := v["token"].(map[string]interface{}); ok {
if v, ok := v["token"].(map[string]any); ok {
v["id"] = "***"
}
// v3 auth methods
if v, ok := v["identity"].(map[string]interface{}); ok {
if v, ok := v["password"].(map[string]interface{}); ok {
if v, ok := v["user"].(map[string]interface{}); ok {
if v, ok := v["identity"].(map[string]any); ok {
if v, ok := v["password"].(map[string]any); ok {
if v, ok := v["user"].(map[string]any); ok {
v["password"] = "***"
}
}
if v, ok := v["application_credential"].(map[string]interface{}); ok {
if v, ok := v["application_credential"].(map[string]any); ok {
v["secret"] = "***"
}
if v, ok := v["token"].(map[string]interface{}); ok {
if v, ok := v["token"].(map[string]any); ok {
v["id"] = "***"
}
}
}

// Mask EC2 access id and body hash
if v, ok := data["credentials"].(map[string]interface{}); ok {
if v, ok := data["credentials"].(map[string]any); ok {
var access string
if s, ok := v["access"]; ok {
access, _ = s.(string)
Expand All @@ -340,17 +337,17 @@ func FormatJSON(raw []byte) (string, error) {
if _, ok := v["body_hash"]; ok {
v["body_hash"] = "***"
}
if v, ok := v["headers"].(map[string]interface{}); ok {
if v, ok := v["headers"].(map[string]any); ok {
if _, ok := v["Authorization"]; ok {
if s, ok := v["Authorization"].(string); ok {
v["Authorization"] = strings.Replace(s, access, "***", -1)
v["Authorization"] = strings.ReplaceAll(s, access, "***")
}
}
}
}

// Ignore the huge catalog output
if v, ok := data["token"].(map[string]interface{}); ok {
if v, ok := data["token"].(map[string]any); ok {
if _, ok := v["catalog"]; ok {
v["catalog"] = "***"
}
Expand Down
4 changes: 2 additions & 2 deletions client/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ Example usage with the custom logger:
Prefix string
}

func (l myLogger) Printf(format string, args ...interface{}) {
log.Debugf("%s [DEBUG] "+format, append([]interface{}{l.Prefix}, args...)...)
func (l myLogger) Printf(format string, args ...any) {
log.Debugf("%s [DEBUG] "+format, append([]any{l.Prefix}, args...)...)
}

func NewComputeV2Client() (*gophercloud.ServiceClient, error) {
Expand Down
8 changes: 4 additions & 4 deletions gnocchi/metric/v1/archivepolicies/requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func Get(ctx context.Context, c *gophercloud.ServiceClient, archivePolicyName st

// CreateOptsBuilder allows extensions to add additional parameters to the Create request.
type CreateOptsBuilder interface {
ToArchivePolicyCreateMap() (map[string]interface{}, error)
ToArchivePolicyCreateMap() (map[string]any, error)
}

// CreateOpts specifies parameters of a new Archive Policy.
Expand Down Expand Up @@ -62,7 +62,7 @@ type ArchivePolicyDefinitionOpts struct {
}

// ToArchivePolicyCreateMap constructs a request body from CreateOpts.
func (opts CreateOpts) ToArchivePolicyCreateMap() (map[string]interface{}, error) {
func (opts CreateOpts) ToArchivePolicyCreateMap() (map[string]any, error) {
return gophercloud.BuildRequestBody(opts, "")
}

Expand All @@ -82,7 +82,7 @@ func Create(ctx context.Context, client *gophercloud.ServiceClient, opts CreateO

// UpdateOptsBuilder allows extensions to add additional parameters to the Update request.
type UpdateOptsBuilder interface {
ToArchivePolicyUpdateMap() (map[string]interface{}, error)
ToArchivePolicyUpdateMap() (map[string]any, error)
}

// UpdateOpts represents options used to update an archive policy.
Expand All @@ -93,7 +93,7 @@ type UpdateOpts struct {
}

// ToArchivePolicyUpdateMap constructs a request body from UpdateOpts.
func (opts UpdateOpts) ToArchivePolicyUpdateMap() (map[string]interface{}, error) {
func (opts UpdateOpts) ToArchivePolicyUpdateMap() (map[string]any, error) {
return gophercloud.BuildRequestBody(opts, "")
}

Expand Down
10 changes: 5 additions & 5 deletions gnocchi/metric/v1/archivepolicies/testing/requests_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func TestListArchivePolicies(t *testing.T) {
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)

fmt.Fprintf(w, ArchivePoliciesListResult)
fmt.Fprint(w, ArchivePoliciesListResult)
})

expected := ListArchivePoliciesExpected
Expand Down Expand Up @@ -56,7 +56,7 @@ func TestListArchivePoliciesAllPages(t *testing.T) {
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)

fmt.Fprintf(w, ArchivePoliciesListResult)
fmt.Fprint(w, ArchivePoliciesListResult)
})

allPages, err := archivepolicies.List(fake.ServiceClient()).AllPages(context.TODO())
Expand All @@ -76,7 +76,7 @@ func TestGetArchivePolicy(t *testing.T) {
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)

fmt.Fprintf(w, ArchivePolicyGetResult)
fmt.Fprint(w, ArchivePolicyGetResult)
})

s, err := archivepolicies.Get(context.TODO(), fake.ServiceClient(), "test_policy").Extract()
Expand Down Expand Up @@ -117,7 +117,7 @@ func TestCreate(t *testing.T) {
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)

fmt.Fprintf(w, ArchivePolicyCreateResponse)
fmt.Fprint(w, ArchivePolicyCreateResponse)
})

opts := archivepolicies.CreateOpts{
Expand Down Expand Up @@ -177,7 +177,7 @@ func TestUpdateArchivePolicy(t *testing.T) {
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)

fmt.Fprintf(w, ArchivePolicyUpdateResponse)
fmt.Fprint(w, ArchivePolicyUpdateResponse)
})

updateOpts := archivepolicies.UpdateOpts{
Expand Down
Loading