diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml index 713c955..fb7fd8d 100644 --- a/.github/workflows/unit.yml +++ b/.github/workflows/unit.yml @@ -1,5 +1,5 @@ -on: [push, pull_request] name: Unit Testing +on: [push, pull_request] jobs: test: runs-on: ubuntu-latest @@ -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 diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 0000000..1565b01 --- /dev/null +++ b/.golangci.yaml @@ -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$ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..de944b9 --- /dev/null +++ b/Makefile @@ -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 diff --git a/client/client.go b/client/client.go index e2cd4ce..198fac6 100644 --- a/client/client.go +++ b/client/client.go @@ -6,7 +6,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "log" "net/http" "sort" @@ -19,14 +18,14 @@ 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...) } @@ -34,7 +33,7 @@ func (DefaultLogger) Printf(format string, args ...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 @@ -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 } @@ -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) @@ -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") @@ -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") @@ -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 { @@ -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) @@ -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"] = "***" } diff --git a/client/doc.go b/client/doc.go index 7315300..c1bebc8 100644 --- a/client/doc.go +++ b/client/doc.go @@ -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) { diff --git a/gnocchi/metric/v1/archivepolicies/requests.go b/gnocchi/metric/v1/archivepolicies/requests.go index dd0c037..cac9c41 100644 --- a/gnocchi/metric/v1/archivepolicies/requests.go +++ b/gnocchi/metric/v1/archivepolicies/requests.go @@ -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. @@ -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, "") } @@ -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. @@ -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, "") } diff --git a/gnocchi/metric/v1/archivepolicies/testing/requests_test.go b/gnocchi/metric/v1/archivepolicies/testing/requests_test.go index 392c1ca..68518a8 100644 --- a/gnocchi/metric/v1/archivepolicies/testing/requests_test.go +++ b/gnocchi/metric/v1/archivepolicies/testing/requests_test.go @@ -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 @@ -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()) @@ -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() @@ -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{ @@ -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{ diff --git a/gnocchi/metric/v1/measures/requests.go b/gnocchi/metric/v1/measures/requests.go index dba9861..a3435e4 100644 --- a/gnocchi/metric/v1/measures/requests.go +++ b/gnocchi/metric/v1/measures/requests.go @@ -2,7 +2,7 @@ package measures import ( "context" - "fmt" + "errors" "net/url" "time" @@ -78,7 +78,7 @@ func List(c *gophercloud.ServiceClient, metricID string, opts ListOptsBuilder) p // CreateOptsBuilder is needed to add measures to the Create request. type CreateOptsBuilder interface { - ToMeasureCreateMap() (map[string]interface{}, error) + ToMeasureCreateMap() (map[string]any, error) } // MeasureOpts represents options of a single measure that can be created in the Gnocchi. @@ -91,7 +91,7 @@ type MeasureOpts struct { } // ToMap is a helper function to convert individual MeasureOpts structure into a sub-map. -func (opts MeasureOpts) ToMap() (map[string]interface{}, error) { +func (opts MeasureOpts) ToMap() (map[string]any, error) { b, err := gophercloud.BuildRequestBody(opts, "") if err != nil { return nil, err @@ -109,8 +109,8 @@ type CreateOpts struct { } // ToMeasureCreateMap constructs a request body from CreateOpts. -func (opts CreateOpts) ToMeasureCreateMap() (map[string]interface{}, error) { - measures := make([]map[string]interface{}, len(opts.Measures)) +func (opts CreateOpts) ToMeasureCreateMap() (map[string]any, error) { + measures := make([]map[string]any, len(opts.Measures)) for i, m := range opts.Measures { measureMap, err := m.ToMap() if err != nil { @@ -118,7 +118,7 @@ func (opts CreateOpts) ToMeasureCreateMap() (map[string]interface{}, error) { } measures[i] = measureMap } - return map[string]interface{}{"measures": measures}, nil + return map[string]any{"measures": measures}, nil } // Create requests the creation of a new measures in the single Gnocchi metric. @@ -140,7 +140,7 @@ func Create(ctx context.Context, client *gophercloud.ServiceClient, metricID str // BatchCreateMetricsOptsBuilder is needed to add measures to the BatchCreateMetrics request. type BatchCreateMetricsOptsBuilder interface { - ToMeasuresBatchCreateMetricsMap() (map[string]interface{}, error) + ToMeasuresBatchCreateMetricsMap() (map[string]any, error) } // BatchCreateMetricsOpts specifies a parameters for creating measures for different metrics in a single request. @@ -156,22 +156,22 @@ type MetricOpts struct { } // ToMap is a helper function to convert individual MetricOpts structure into a sub-map. -func (opts MetricOpts) ToMap() (map[string]interface{}, error) { +func (opts MetricOpts) ToMap() (map[string]any, error) { // Check provided MetricOpts fields. if opts.ID == "" { errMsg := "missing input for the MetricOpts 'ID' argument" - return nil, fmt.Errorf(errMsg) + return nil, errors.New(errMsg) } if opts.Measures == nil { errMsg := "missing input for the MetricOpts 'Measures' argument" - return nil, fmt.Errorf(errMsg) + return nil, errors.New(errMsg) } // measures is a slice of measures maps. - measures := make([]map[string]interface{}, len(opts.Measures)) + measures := make([]map[string]any, len(opts.Measures)) // metricOpts is an internal map representation of the MetricOpts struct. - metricOpts := make(map[string]interface{}) + metricOpts := make(map[string]any) for i, measure := range opts.Measures { measureMap, err := measure.ToMap() @@ -186,9 +186,9 @@ func (opts MetricOpts) ToMap() (map[string]interface{}, error) { } // ToMeasuresBatchCreateMetricsMap constructs a request body from BatchCreateMetricsOpts. -func (opts BatchCreateMetricsOpts) ToMeasuresBatchCreateMetricsMap() (map[string]interface{}, error) { +func (opts BatchCreateMetricsOpts) ToMeasuresBatchCreateMetricsMap() (map[string]any, error) { // batchCreateMetricsOpts is an internal representation of the BatchCreateMetricsOpts struct. - batchCreateMetricsOpts := make(map[string]interface{}) + batchCreateMetricsOpts := make(map[string]any) for _, metricOpts := range opts { metricOptsMap, err := metricOpts.ToMap() @@ -200,7 +200,7 @@ func (opts BatchCreateMetricsOpts) ToMeasuresBatchCreateMetricsMap() (map[string } } - return map[string]interface{}{"batchCreateMetrics": batchCreateMetricsOpts}, nil + return map[string]any{"batchCreateMetrics": batchCreateMetricsOpts}, nil } // BatchCreateMetrics requests the creation of a new measures for different metrics. @@ -224,7 +224,7 @@ func BatchCreateMetrics(ctx context.Context, client *gophercloud.ServiceClient, // BatchCreateResourcesMetricsOptsBuilder is needed to add measures to the BatchCreateResourcesMetrics request. type BatchCreateResourcesMetricsOptsBuilder interface { // ToMeasuresBatchCreateResourcesMetricsMap builds a request body. - ToMeasuresBatchCreateResourcesMetricsMap() (map[string]interface{}, error) + ToMeasuresBatchCreateResourcesMetricsMap() (map[string]any, error) // ToMeasuresBatchCreateResourcesMetricsQuery builds a query string. ToMeasuresBatchCreateResourcesMetricsQuery() (string, error) @@ -249,25 +249,25 @@ type BatchResourcesMetricsOpts struct { } // ToMap is a helper function to convert individual BatchResourcesMetricsOpts structure into a sub-map. -func (opts BatchResourcesMetricsOpts) ToMap() (map[string]interface{}, error) { +func (opts BatchResourcesMetricsOpts) ToMap() (map[string]any, error) { // Check provided BatchResourcesMetricsOpts fields. if opts.ResourceID == "" { errMsg := "missing input for the BatchResourcesMetricsOpts 'ResourceID' argument" - return nil, fmt.Errorf(errMsg) + return nil, errors.New(errMsg) } if opts.ResourcesMetrics == nil { errMsg := "missing input for the BatchResourcesMetricsOpts 'ResourcesMetrics' argument" - return nil, fmt.Errorf(errMsg) + return nil, errors.New(errMsg) } // batchResourcesMetricsOpts is an internal map representation of the BatchResourcesMetricsOpts struct. - batchResourcesMetricsOpts := make(map[string]interface{}) + batchResourcesMetricsOpts := make(map[string]any) // resourcesMetricsMaps is a temporary slice that contains different metrics for a single resource. - resourcesMetricsMaps := make([]map[string]interface{}, len(opts.ResourcesMetrics)) + resourcesMetricsMaps := make([]map[string]any, len(opts.ResourcesMetrics)) // resourcesMetricsOptsMap is a temporary map that contains join of different maps from resourcesMetricsMaps slice. - resourcesMetricsOptsMap := make(map[string]interface{}) + resourcesMetricsOptsMap := make(map[string]any) // Populate the temporary resourcesMetricsMaps slice. for i, resourcesMetrics := range opts.ResourcesMetrics { @@ -308,25 +308,25 @@ type ResourcesMetricsOpts struct { } // ToMap is a helper function to convert individual ResourcesMetricsOpts structure into a sub-map. -func (opts ResourcesMetricsOpts) ToMap() (map[string]interface{}, error) { +func (opts ResourcesMetricsOpts) ToMap() (map[string]any, error) { // Check provided ResourcesMetricsOpts fields. if opts.MetricName == "" { errMsg := "missing input for the ResourcesMetricsOpts 'MetricName' argument" - return nil, fmt.Errorf(errMsg) + return nil, errors.New(errMsg) } if opts.Measures == nil { errMsg := "missing input for the ResourcesMetricsOpts 'Measures' argument" - return nil, fmt.Errorf(errMsg) + return nil, errors.New(errMsg) } // measures is a slice of measures maps. - measures := make([]map[string]interface{}, len(opts.Measures)) + measures := make([]map[string]any, len(opts.Measures)) // resourcesMetricsOpts is an internal map representation of the ResourcesMetricsOpts struct. - resourcesMetricsOpts := make(map[string]interface{}) + resourcesMetricsOpts := make(map[string]any) // metricOpts is an internal nested map for each metric in the resourcesMetricsOpts. - metricOpts := make(map[string]interface{}) + metricOpts := make(map[string]any) // Populate metricOpts with values from provided opts. if opts.ArchivePolicyName != "" { @@ -350,10 +350,10 @@ func (opts ResourcesMetricsOpts) ToMap() (map[string]interface{}, error) { } // ToMeasuresBatchCreateResourcesMetricsMap constructs a request body from the BatchCreateResourcesMetricsOpts. -func (opts BatchCreateResourcesMetricsOpts) ToMeasuresBatchCreateResourcesMetricsMap() (map[string]interface{}, error) { +func (opts BatchCreateResourcesMetricsOpts) ToMeasuresBatchCreateResourcesMetricsMap() (map[string]any, error) { // batchCreateResourcesMetricsOpts is an internal representation of the // BatchCreateResourcesMetricsOpts's BatchResourcesMetrics field. - batchCreateResourcesMetricsOpts := make(map[string]interface{}) + batchCreateResourcesMetricsOpts := make(map[string]any) for _, resourceMetricsOpts := range opts.BatchResourcesMetrics { resourceMetricsOptsMap, err := resourceMetricsOpts.ToMap() @@ -365,7 +365,7 @@ func (opts BatchCreateResourcesMetricsOpts) ToMeasuresBatchCreateResourcesMetric } } - return map[string]interface{}{"batchCreateResourcesMetrics": batchCreateResourcesMetricsOpts}, nil + return map[string]any{"batchCreateResourcesMetrics": batchCreateResourcesMetricsOpts}, nil } // ToMeasuresBatchCreateResourcesMetricsQuery formats the BatchCreateResourcesMetricsOpts into a query string. diff --git a/gnocchi/metric/v1/measures/results.go b/gnocchi/metric/v1/measures/results.go index 1388561..9d752f6 100644 --- a/gnocchi/metric/v1/measures/results.go +++ b/gnocchi/metric/v1/measures/results.go @@ -64,7 +64,7 @@ Gnocchi APIv1 returns measures in a such format: Helper unmarshals every nested array into the Measure type. */ func (r *Measure) UnmarshalJSON(b []byte) error { - var measuresSlice []interface{} + var measuresSlice []any err := json.Unmarshal(b, &measuresSlice) if err != nil { return err @@ -72,8 +72,7 @@ func (r *Measure) UnmarshalJSON(b []byte) error { // We need to check that a measure contains all needed data. if len(measuresSlice) != 3 { - errMsg := fmt.Sprintf("got an invalid measure: %v", measuresSlice) - return fmt.Errorf(errMsg) + return fmt.Errorf("got an invalid measure: %v", measuresSlice) } type tmp Measure @@ -86,8 +85,7 @@ func (r *Measure) UnmarshalJSON(b []byte) error { var timeStamp string var ok bool if timeStamp, ok = measuresSlice[0].(string); !ok { - errMsg := fmt.Sprintf("got an invalid timestamp of a measure %v: %v", measuresSlice, measuresSlice[0]) - return fmt.Errorf(errMsg) + return fmt.Errorf("got an invalid timestamp of a measure %v: %v", measuresSlice, measuresSlice[0]) } r.Timestamp, err = time.Parse(gnocchi.RFC3339NanoTimezone, timeStamp) if err != nil { @@ -96,14 +94,12 @@ func (r *Measure) UnmarshalJSON(b []byte) error { // Populate a measure's granularity. if r.Granularity, ok = measuresSlice[1].(float64); !ok { - errMsg := fmt.Sprintf("got an invalid granularity of a measure %v: %v", measuresSlice, measuresSlice[1]) - return fmt.Errorf(errMsg) + return fmt.Errorf("got an invalid granularity of a measure %v: %v", measuresSlice, measuresSlice[1]) } // Populate a measure's value. if r.Value = measuresSlice[2].(float64); !ok { - errMsg := fmt.Sprintf("got an invalid value of a measure %v: %v", measuresSlice, measuresSlice[2]) - return fmt.Errorf(errMsg) + return fmt.Errorf("got an invalid value of a measure %v: %v", measuresSlice, measuresSlice[2]) } return nil diff --git a/gnocchi/metric/v1/measures/testing/requests_test.go b/gnocchi/metric/v1/measures/testing/requests_test.go index befe5c3..9a7b1ec 100644 --- a/gnocchi/metric/v1/measures/testing/requests_test.go +++ b/gnocchi/metric/v1/measures/testing/requests_test.go @@ -24,7 +24,7 @@ func TestListMeasures(t *testing.T) { w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - fmt.Fprintf(w, MeasuresListResult) + fmt.Fprint(w, MeasuresListResult) }) metricID := "9e5a6441-1044-4181-b66e-34e180753040" diff --git a/gnocchi/metric/v1/metrics/requests.go b/gnocchi/metric/v1/metrics/requests.go index f22fb08..0e758c1 100644 --- a/gnocchi/metric/v1/metrics/requests.go +++ b/gnocchi/metric/v1/metrics/requests.go @@ -62,7 +62,7 @@ func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { pager := pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page { p := MetricPage{pagination.MarkerPageBase{PageResult: r}} - p.MarkerPageBase.Owner = p + p.Owner = p return p }) @@ -79,7 +79,7 @@ func Get(ctx context.Context, c *gophercloud.ServiceClient, metricID string) (r // CreateOptsBuilder allows to add additional parameters to the // Create request. type CreateOptsBuilder interface { - ToMetricCreateMap() (map[string]interface{}, error) + ToMetricCreateMap() (map[string]any, error) } // CreateOpts specifies parameters of a new Gnocchi metric. @@ -102,7 +102,7 @@ type CreateOpts struct { } // ToMetricCreateMap constructs a request body from CreateOpts. -func (opts CreateOpts) ToMetricCreateMap() (map[string]interface{}, error) { +func (opts CreateOpts) ToMetricCreateMap() (map[string]any, error) { b, err := gophercloud.BuildRequestBody(opts, "") if err != nil { return nil, err diff --git a/gnocchi/metric/v1/metrics/testing/requests_test.go b/gnocchi/metric/v1/metrics/testing/requests_test.go index 9ee549d..993c549 100644 --- a/gnocchi/metric/v1/metrics/testing/requests_test.go +++ b/gnocchi/metric/v1/metrics/testing/requests_test.go @@ -25,13 +25,14 @@ func TestList(t *testing.T) { w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - r.ParseForm() + err := r.ParseForm() + th.AssertNoErr(t, err) marker := r.Form.Get("marker") switch marker { case "": - fmt.Fprintf(w, MetricsListResult) + fmt.Fprint(w, MetricsListResult) case "6dbc97c5-bfdf-47a2-b184-02e7fa348d21": - fmt.Fprintf(w, `[]`) + fmt.Fprint(w, `[]`) default: t.Fatalf("/v1/metric invoked with unexpected marker=[%s]", marker) } @@ -39,7 +40,7 @@ func TestList(t *testing.T) { count := 0 - metrics.List(fake.ServiceClient(), metrics.ListOpts{}).EachPage(context.TODO(), func(_ context.Context, page pagination.Page) (bool, error) { + err := metrics.List(fake.ServiceClient(), metrics.ListOpts{}).EachPage(context.TODO(), func(_ context.Context, page pagination.Page) (bool, error) { count++ actual, err := metrics.ExtractMetrics(page) if err != nil { @@ -56,6 +57,7 @@ func TestList(t *testing.T) { return true, nil }) + th.AssertNoErr(t, err) if count != 1 { t.Errorf("Expected 1 page, got %d", count) @@ -73,7 +75,7 @@ func TestGet(t *testing.T) { w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - fmt.Fprintf(w, MetricGetResult) + fmt.Fprint(w, MetricGetResult) }) s, err := metrics.Get(context.TODO(), fake.ServiceClient(), "0ddf61cf-3747-4f75-bf13-13c28ff03ae3").Extract() @@ -117,7 +119,7 @@ func TestGet(t *testing.T) { EndedAt: time.Time{}, Type: "compute_instance_network", UserID: "bd5874d666624b24a9f01c128871e4ac", - ExtraAttributes: map[string]interface{}{}, + ExtraAttributes: map[string]any{}, }) th.AssertEquals(t, s.Unit, "packet/s") } @@ -136,7 +138,7 @@ func TestCreate(t *testing.T) { w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) - fmt.Fprintf(w, MetricCreateResponse) + fmt.Fprint(w, MetricCreateResponse) }) opts := metrics.CreateOpts{ diff --git a/gnocchi/metric/v1/resources/doc.go b/gnocchi/metric/v1/resources/doc.go index 36a56a2..5fd2f1f 100644 --- a/gnocchi/metric/v1/resources/doc.go +++ b/gnocchi/metric/v1/resources/doc.go @@ -49,7 +49,7 @@ Example of Creating a resource with links to some existing metrics with a starti ID: "23d5d3f7-9dfa-4f73-b72b-8b0b0063ec55", ProjectID: "4154f088-8333-4e04-94c4-1155c33c0fc9", StartedAt: &startedAt, - Metrics: map[string]interface{}{ + Metrics: map[string]any{ "disk.read.bytes.rate": "ed1bb76f-6ccc-4ad2-994c-dbb19ddccbae", "disk.write.bytes.rate": "0a2da84d-4753-43f5-a65f-0f8d44d2766c", }, @@ -66,7 +66,7 @@ Example of Creating a resource and a metric a the same time ID: "23d5d3f7-9dfa-4f73-b72b-8b0b0063ec55", ProjectID: "4154f088-8333-4e04-94c4-1155c33c0fc9", UserID: "bd5874d6-6662-4b24-a9f01c128871e4ac", - Metrics: map[string]interface{}{ + Metrics: map[string]any{ "cpu.delta": map[string]string{ "archive_policy_name": "medium", }, @@ -93,7 +93,7 @@ Example of Updating a resource Example of Updating a resource and associating an existing metric to it endedAt := time.Date(2018, 1, 16, 12, 0, 0, 0, time.UTC) - metrics := map[string]interface{}{ + metrics := map[string]any{ "disk.write.bytes.rate": "0a2da84d-4753-43f5-a65f-0f8d44d2766c", } updateOpts := resources.UpdateOpts{ @@ -109,7 +109,7 @@ Example of Updating a resource and associating an existing metric to it Example of Updating a resource and creating an associated metric at the same time - metrics := map[string]interface{}{ + metrics := map[string]any{ "cpu.delta": map[string]string{ "archive_policy_name": "medium", }, diff --git a/gnocchi/metric/v1/resources/requests.go b/gnocchi/metric/v1/resources/requests.go index 481637e..7d678ba 100644 --- a/gnocchi/metric/v1/resources/requests.go +++ b/gnocchi/metric/v1/resources/requests.go @@ -55,7 +55,7 @@ func List(c *gophercloud.ServiceClient, opts ListOptsBuilder, resourceType strin } pager := pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page { p := ResourcePage{pagination.MarkerPageBase{PageResult: r}} - p.MarkerPageBase.Owner = p + p.Owner = p return p }) @@ -72,7 +72,7 @@ func Get(ctx context.Context, c *gophercloud.ServiceClient, resourceType string, // CreateOptsBuilder allows to add additional parameters to the // Create request. type CreateOptsBuilder interface { - ToResourceCreateMap() (map[string]interface{}, error) + ToResourceCreateMap() (map[string]any, error) } // CreateOpts specifies parameters of a new Gnocchi resource. @@ -83,7 +83,7 @@ type CreateOpts struct { // Metrics field can be used to link existing metrics in the resource // or to create metrics with the resource at the same time to save // some requests. - Metrics map[string]interface{} `json:"metrics,omitempty"` + Metrics map[string]any `json:"metrics,omitempty"` // ProjectID is the Identity project of the resource. ProjectID string `json:"project_id,omitempty"` @@ -99,11 +99,11 @@ type CreateOpts struct { // ExtraAttributes is a collection of keys and values that can be found in resources // of different resource types. - ExtraAttributes map[string]interface{} `json:"-"` + ExtraAttributes map[string]any `json:"-"` } // ToResourceCreateMap constructs a request body from CreateOpts. -func (opts CreateOpts) ToResourceCreateMap() (map[string]interface{}, error) { +func (opts CreateOpts) ToResourceCreateMap() (map[string]any, error) { b, err := gophercloud.BuildRequestBody(opts, "") if err != nil { return nil, err @@ -143,7 +143,7 @@ func Create(ctx context.Context, client *gophercloud.ServiceClient, resourceType // UpdateOptsBuilder allows extensions to add additional parameters to the // Update request. type UpdateOptsBuilder interface { - ToResourceUpdateMap() (map[string]interface{}, error) + ToResourceUpdateMap() (map[string]any, error) } // UpdateOpts represents options used to update a network. @@ -151,7 +151,7 @@ type UpdateOpts struct { // Metrics field can be used to link existing metrics in the resource // or to create metrics and update the resource at the same time to save // some requests. - Metrics *map[string]interface{} `json:"metrics,omitempty"` + Metrics *map[string]any `json:"metrics,omitempty"` // ProjectID is the Identity project of the resource. ProjectID string `json:"project_id,omitempty"` @@ -167,11 +167,11 @@ type UpdateOpts struct { // ExtraAttributes is a collection of keys and values that can be found in resources // of different resource types. - ExtraAttributes map[string]interface{} `json:"-"` + ExtraAttributes map[string]any `json:"-"` } // ToResourceUpdateMap builds a request body from UpdateOpts. -func (opts UpdateOpts) ToResourceUpdateMap() (map[string]interface{}, error) { +func (opts UpdateOpts) ToResourceUpdateMap() (map[string]any, error) { b, err := gophercloud.BuildRequestBody(opts, "") if err != nil { return nil, err diff --git a/gnocchi/metric/v1/resources/results.go b/gnocchi/metric/v1/resources/results.go index a5e7d90..8c7b042 100644 --- a/gnocchi/metric/v1/resources/results.go +++ b/gnocchi/metric/v1/resources/results.go @@ -95,7 +95,7 @@ type Resource struct { // ExtraAttributes is a collection of keys and values that can be found in resources // of different resource types. - ExtraAttributes map[string]interface{} `json:"-"` + ExtraAttributes map[string]any `json:"-"` } // UnmarshalJSON helps to unmarshal Resource fields into needed values. @@ -103,7 +103,7 @@ func (r *Resource) UnmarshalJSON(b []byte) error { type tmp Resource var s struct { tmp - ExtraAttributes map[string]interface{} `json:"extra_attributes"` + ExtraAttributes map[string]any `json:"extra_attributes"` RevisionStart gnocchi.JSONRFC3339NanoTimezone `json:"revision_start"` RevisionEnd gnocchi.JSONRFC3339NanoTimezone `json:"revision_end"` StartedAt gnocchi.JSONRFC3339NanoTimezone `json:"started_at"` @@ -126,12 +126,12 @@ func (r *Resource) UnmarshalJSON(b []byte) error { if s.ExtraAttributes != nil { r.ExtraAttributes = s.ExtraAttributes } else { - var result interface{} + var result any err := json.Unmarshal(b, &result) if err != nil { return err } - if resultMap, ok := result.(map[string]interface{}); ok { + if resultMap, ok := result.(map[string]any); ok { delete(resultMap, "revision_start") delete(resultMap, "revision_end") delete(resultMap, "started_at") diff --git a/gnocchi/metric/v1/resources/testing/fixtures.go b/gnocchi/metric/v1/resources/testing/fixtures.go index 9f9ab40..745f844 100644 --- a/gnocchi/metric/v1/resources/testing/fixtures.go +++ b/gnocchi/metric/v1/resources/testing/fixtures.go @@ -68,7 +68,7 @@ var Resource1 = resources.Resource{ EndedAt: time.Time{}, Type: "compute_instance", UserID: "bd5874d666624b24a9f01c128871e4ac", - ExtraAttributes: map[string]interface{}{ + ExtraAttributes: map[string]any{ "display_name": "MyInstance00", "flavor_name": "2CPU4G", "host": "compute010", @@ -93,7 +93,7 @@ var Resource2 = resources.Resource{ EndedAt: time.Time{}, Type: "compute_instance_disk", UserID: "bd5874d666624b24a9f01c128871e4ac", - ExtraAttributes: map[string]interface{}{ + ExtraAttributes: map[string]any{ "disk_device_name": "sdb", }, } diff --git a/gnocchi/metric/v1/resources/testing/requests_test.go b/gnocchi/metric/v1/resources/testing/requests_test.go index 30c0a53..f57e608 100644 --- a/gnocchi/metric/v1/resources/testing/requests_test.go +++ b/gnocchi/metric/v1/resources/testing/requests_test.go @@ -23,13 +23,14 @@ func TestList(t *testing.T) { w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - r.ParseForm() + err := r.ParseForm() + th.AssertNoErr(t, err) marker := r.Form.Get("marker") switch marker { case "": - fmt.Fprintf(w, ResourceListResult) + fmt.Fprint(w, ResourceListResult) case "789a7f65-977d-40f4-beed-f717100125f5": - fmt.Fprintf(w, `[]`) + fmt.Fprint(w, `[]`) default: t.Fatalf("/v1/resources invoked with unexpected marker=[%s]", marker) } @@ -37,7 +38,7 @@ func TestList(t *testing.T) { count := 0 - resources.List(fake.ServiceClient(), resources.ListOpts{}, "generic").EachPage(context.TODO(), func(_ context.Context, page pagination.Page) (bool, error) { + err := resources.List(fake.ServiceClient(), resources.ListOpts{}, "generic").EachPage(context.TODO(), func(_ context.Context, page pagination.Page) (bool, error) { count++ actual, err := resources.ExtractResources(page) if err != nil { @@ -54,6 +55,7 @@ func TestList(t *testing.T) { return true, nil }) + th.AssertNoErr(t, err) if count != 1 { t.Errorf("Expected 1 page, got %d", count) @@ -71,7 +73,7 @@ func TestGet(t *testing.T) { w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - fmt.Fprintf(w, ResourceGetResult) + fmt.Fprint(w, ResourceGetResult) }) s, err := resources.Get(context.TODO(), fake.ServiceClient(), "compute_instance_network", "75274f99-faf6-4112-a6d5-2794cb07c789").Extract() @@ -95,7 +97,7 @@ func TestGet(t *testing.T) { th.AssertEquals(t, s.EndedAt, time.Time{}) th.AssertEquals(t, s.Type, "compute_instance_network") th.AssertEquals(t, s.UserID, "bd5874d666624b24a9f01c128871e4ac") - th.AssertDeepEquals(t, s.ExtraAttributes, map[string]interface{}{ + th.AssertDeepEquals(t, s.ExtraAttributes, map[string]any{ "iface_name": "eth0", }) } @@ -114,7 +116,7 @@ func TestCreateWithoutMetrics(t *testing.T) { w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) - fmt.Fprintf(w, ResourceCreateWithoutMetricsResult) + fmt.Fprint(w, ResourceCreateWithoutMetricsResult) }) opts := resources.CreateOpts{ @@ -154,7 +156,7 @@ func TestCreateLinkMetrics(t *testing.T) { w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) - fmt.Fprintf(w, ResourceCreateLinkMetricsResult) + fmt.Fprint(w, ResourceCreateLinkMetricsResult) }) startedAt := time.Date(2018, 1, 2, 23, 23, 34, 0, time.UTC) @@ -165,7 +167,7 @@ func TestCreateLinkMetrics(t *testing.T) { UserID: "bd5874d6-6662-4b24-a9f01c128871e4ac", StartedAt: &startedAt, EndedAt: &endedAt, - Metrics: map[string]interface{}{ + Metrics: map[string]any{ "network.incoming.bytes.rate": "01b2953e-de74-448a-a305-c84440697933", "network.outgoing.bytes.rate": "dc9f3198-155b-4b88-a92c-58a3853ce2b2", }, @@ -205,7 +207,7 @@ func TestCreateWithMetrics(t *testing.T) { w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) - fmt.Fprintf(w, ResourceCreateWithMetricsResult) + fmt.Fprint(w, ResourceCreateWithMetricsResult) }) endedAt := time.Date(2018, 1, 9, 20, 0, 0, 0, time.UTC) @@ -214,7 +216,7 @@ func TestCreateWithMetrics(t *testing.T) { ProjectID: "4154f088-8333-4e04-94c4-1155c33c0fc9", UserID: "bd5874d6-6662-4b24-a9f01c128871e4ac", EndedAt: &endedAt, - Metrics: map[string]interface{}{ + Metrics: map[string]any{ "disk.write.bytes.rate": map[string]string{ "archive_policy_name": "high", }, @@ -254,11 +256,11 @@ func TestUpdateLinkMetrics(t *testing.T) { w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - fmt.Fprintf(w, ResourceUpdateLinkMetricsResponse) + fmt.Fprint(w, ResourceUpdateLinkMetricsResponse) }) endedAt := time.Date(2018, 1, 14, 13, 0, 0, 0, time.UTC) - metrics := map[string]interface{}{ + metrics := map[string]any{ "network.incoming.bytes.rate": "01b2953e-de74-448a-a305-c84440697933", } updateOpts := resources.UpdateOpts{ @@ -299,11 +301,11 @@ func TestUpdateCreateMetrics(t *testing.T) { w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - fmt.Fprintf(w, ResourceUpdateCreateMetricsResponse) + fmt.Fprint(w, ResourceUpdateCreateMetricsResponse) }) startedAt := time.Date(2018, 1, 12, 11, 0, 0, 0, time.UTC) - metrics := map[string]interface{}{ + metrics := map[string]any{ "disk.read.bytes.rate": map[string]string{ "archive_policy_name": "low", }, diff --git a/gnocchi/metric/v1/resourcetypes/doc.go b/gnocchi/metric/v1/resourcetypes/doc.go index 1ee40e7..cb2ad90 100644 --- a/gnocchi/metric/v1/resourcetypes/doc.go +++ b/gnocchi/metric/v1/resourcetypes/doc.go @@ -32,14 +32,14 @@ Example of Creating a resource type Attributes: map[string]resourcetypes.AttributeOpts{ "port_name": resourcetypes.AttributeOpts{ Type: "string", - Details: map[string]interface{}{ + Details: map[string]any{ "max_length": 128, "required": false, }, }, "port_id": resourcetypes.AttributeOpts{ Type: "uuid", - Details: map[string]interface{}{ + Details: map[string]any{ "required": true, }, }, @@ -53,16 +53,16 @@ Example of Creating a resource type Example of Updating a resource type enabledAttributeOptions := resourcetypes.AttributeOpts{ - Details: map[string]interface{}{ + Details: map[string]any{ "required": true, - "options": map[string]interface{}{ + "options": map[string]any{ "fill": true, }, }, Type: "bool", } parendIDAttributeOptions := resourcetypes.AttributeOpts{ - Details: map[string]interface{}{ + Details: map[string]any{ "required": false, }, Type: "uuid", diff --git a/gnocchi/metric/v1/resourcetypes/requests.go b/gnocchi/metric/v1/resourcetypes/requests.go index bd1cdb1..7ba6cd2 100644 --- a/gnocchi/metric/v1/resourcetypes/requests.go +++ b/gnocchi/metric/v1/resourcetypes/requests.go @@ -2,7 +2,7 @@ package resourcetypes import ( "context" - "fmt" + "errors" "strings" "github.com/gophercloud/gophercloud/v2" @@ -25,7 +25,7 @@ func Get(ctx context.Context, c *gophercloud.ServiceClient, resourceTypeName str // CreateOptsBuilder allows to add additional parameters to the Create request. type CreateOptsBuilder interface { - ToResourceTypeCreateMap() (map[string]interface{}, error) + ToResourceTypeCreateMap() (map[string]any, error) } // AttributeOpts represents options of a single resource type attribute that @@ -35,11 +35,11 @@ type AttributeOpts struct { Type string `json:"type"` // Details represents different attribute fields. - Details map[string]interface{} `json:"-"` + Details map[string]any `json:"-"` } // ToMap is a helper function to convert individual AttributeOpts structure into a sub-map. -func (opts AttributeOpts) ToMap() (map[string]interface{}, error) { +func (opts AttributeOpts) ToMap() (map[string]any, error) { b, err := gophercloud.BuildRequestBody(opts, "") if err != nil { return nil, err @@ -62,7 +62,7 @@ type CreateOpts struct { } // ToResourceTypeCreateMap constructs a request body from CreateOpts. -func (opts CreateOpts) ToResourceTypeCreateMap() (map[string]interface{}, error) { +func (opts CreateOpts) ToResourceTypeCreateMap() (map[string]any, error) { b, err := gophercloud.BuildRequestBody(opts, "") if err != nil { return nil, err @@ -73,7 +73,7 @@ func (opts CreateOpts) ToResourceTypeCreateMap() (map[string]interface{}, error) return b, nil } - attributes := make(map[string]interface{}, len(opts.Attributes)) + attributes := make(map[string]any, len(opts.Attributes)) for k, v := range opts.Attributes { attributesMap, err := v.ToMap() if err != nil { @@ -118,7 +118,7 @@ const ( // UpdateOptsBuilder allows to add additional parameters to the Update request. type UpdateOptsBuilder interface { - ToResourceTypeUpdateMap() ([]map[string]interface{}, error) + ToResourceTypeUpdateMap() ([]map[string]any, error) } // UpdateOpts specifies parameters for a Gnocchi resource type update request. @@ -142,16 +142,16 @@ type AttributeUpdateOpts struct { } // ToResourceTypeUpdateMap constructs a request body from UpdateOpts. -func (opts UpdateOpts) ToResourceTypeUpdateMap() ([]map[string]interface{}, error) { +func (opts UpdateOpts) ToResourceTypeUpdateMap() ([]map[string]any, error) { if len(opts.Attributes) == 0 { - return nil, fmt.Errorf("provided Gnocchi resource type UpdateOpts is empty") + return nil, errors.New("provided Gnocchi resource type UpdateOpts is empty") } - updateOptsMaps := make([]map[string]interface{}, len(opts.Attributes)) + updateOptsMaps := make([]map[string]any, len(opts.Attributes)) // Populate a map for every attribute. for i, attributeUpdateOpts := range opts.Attributes { - attributeUpdateOptsMap := make(map[string]interface{}) + attributeUpdateOptsMap := make(map[string]any) // Populate attribute value map if provided. if attributeUpdateOpts.Value != nil { diff --git a/gnocchi/metric/v1/resourcetypes/results.go b/gnocchi/metric/v1/resourcetypes/results.go index bc9a0f9..13f23a2 100644 --- a/gnocchi/metric/v1/resourcetypes/results.go +++ b/gnocchi/metric/v1/resourcetypes/results.go @@ -60,7 +60,7 @@ type Attribute struct { Type string `json:"type"` // Details represents different attribute fields. - Details map[string]interface{} + Details map[string]any } // UnmarshalJSON helps to unmarshal ResourceType fields into needed values. @@ -68,7 +68,7 @@ func (r *ResourceType) UnmarshalJSON(b []byte) error { type tmp ResourceType var s struct { tmp - Attributes map[string]interface{} `json:"attributes"` + Attributes map[string]any `json:"attributes"` } err := json.Unmarshal(b, &s) if err != nil { @@ -84,9 +84,9 @@ func (r *ResourceType) UnmarshalJSON(b []byte) error { attributes := make(map[string]Attribute) for attributeName, attributeValues := range s.Attributes { attribute := new(Attribute) - attribute.Details = make(map[string]interface{}) + attribute.Details = make(map[string]any) - attributeValuesMap, ok := attributeValues.(map[string]interface{}) + attributeValuesMap, ok := attributeValues.(map[string]any) if !ok { // Got some strange resource type attribute representation, skip it. continue diff --git a/gnocchi/metric/v1/resourcetypes/testing/fixtures.go b/gnocchi/metric/v1/resourcetypes/testing/fixtures.go index 445d1ce..e1c1829 100644 --- a/gnocchi/metric/v1/resourcetypes/testing/fixtures.go +++ b/gnocchi/metric/v1/resourcetypes/testing/fixtures.go @@ -47,7 +47,7 @@ var ResourceType2 = resourcetypes.ResourceType{ Attributes: map[string]resourcetypes.Attribute{ "parent_id": { Type: "uuid", - Details: map[string]interface{}{ + Details: map[string]any{ "required": false, }, }, @@ -61,7 +61,7 @@ var ResourceType3 = resourcetypes.ResourceType{ Attributes: map[string]resourcetypes.Attribute{ "host": { Type: "string", - Details: map[string]interface{}{ + Details: map[string]any{ "max_length": float64(128), "min_length": float64(0), "required": true, diff --git a/gnocchi/metric/v1/resourcetypes/testing/requests_test.go b/gnocchi/metric/v1/resourcetypes/testing/requests_test.go index de081fd..594a115 100644 --- a/gnocchi/metric/v1/resourcetypes/testing/requests_test.go +++ b/gnocchi/metric/v1/resourcetypes/testing/requests_test.go @@ -23,12 +23,12 @@ func TestList(t *testing.T) { w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - fmt.Fprintf(w, ResourceTypeListResult) + fmt.Fprint(w, ResourceTypeListResult) }) count := 0 - resourcetypes.List(fake.ServiceClient()).EachPage(context.TODO(), func(_ context.Context, page pagination.Page) (bool, error) { + err := resourcetypes.List(fake.ServiceClient()).EachPage(context.TODO(), func(_ context.Context, page pagination.Page) (bool, error) { count++ actual, err := resourcetypes.ExtractResourceTypes(page) if err != nil { @@ -46,6 +46,7 @@ func TestList(t *testing.T) { return true, nil }) + th.AssertNoErr(t, err) if count != 1 { t.Errorf("Expected 1 page, got %d", count) @@ -63,7 +64,7 @@ func TestGet(t *testing.T) { w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - fmt.Fprintf(w, ResourceTypeGetResult) + fmt.Fprint(w, ResourceTypeGetResult) }) s, err := resourcetypes.Get(context.TODO(), fake.ServiceClient(), "compute_instance").Extract() @@ -74,7 +75,7 @@ func TestGet(t *testing.T) { th.AssertDeepEquals(t, s.Attributes, map[string]resourcetypes.Attribute{ "host": { Type: "string", - Details: map[string]interface{}{ + Details: map[string]any{ "max_length": float64(255), "min_length": float64(0), "required": true, @@ -82,7 +83,7 @@ func TestGet(t *testing.T) { }, "image_ref": { Type: "uuid", - Details: map[string]interface{}{ + Details: map[string]any{ "required": false, }, }, @@ -103,7 +104,7 @@ func TestCreateWithoutAttributes(t *testing.T) { w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) - fmt.Fprintf(w, ResourceTypeCreateWithoutAttributesResult) + fmt.Fprint(w, ResourceTypeCreateWithoutAttributesResult) }) opts := resourcetypes.CreateOpts{ @@ -131,7 +132,7 @@ func TestCreateWithAttributes(t *testing.T) { w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) - fmt.Fprintf(w, ResourceTypeCreateWithAttributesResult) + fmt.Fprint(w, ResourceTypeCreateWithAttributesResult) }) opts := resourcetypes.CreateOpts{ @@ -139,14 +140,14 @@ func TestCreateWithAttributes(t *testing.T) { Attributes: map[string]resourcetypes.AttributeOpts{ "port_name": { Type: "string", - Details: map[string]interface{}{ + Details: map[string]any{ "max_length": 128, "required": false, }, }, "port_id": { Type: "uuid", - Details: map[string]interface{}{ + Details: map[string]any{ "required": true, }, }, @@ -160,7 +161,7 @@ func TestCreateWithAttributes(t *testing.T) { th.AssertDeepEquals(t, s.Attributes, map[string]resourcetypes.Attribute{ "port_name": { Type: "string", - Details: map[string]interface{}{ + Details: map[string]any{ "max_length": float64(128), "min_length": float64(0), "required": false, @@ -168,7 +169,7 @@ func TestCreateWithAttributes(t *testing.T) { }, "port_id": { Type: "uuid", - Details: map[string]interface{}{ + Details: map[string]any{ "required": true, }, }, @@ -189,20 +190,20 @@ func TestUpdate(t *testing.T) { w.Header().Add("Content-Type", "application/json-patch+json") w.WriteHeader(http.StatusOK) - fmt.Fprintf(w, ResourceTypeUpdateResult) + fmt.Fprint(w, ResourceTypeUpdateResult) }) enabledAttributeOptions := resourcetypes.AttributeOpts{ - Details: map[string]interface{}{ + Details: map[string]any{ "required": true, - "options": map[string]interface{}{ + "options": map[string]any{ "fill": true, }, }, Type: "bool", } parendIDAttributeOptions := resourcetypes.AttributeOpts{ - Details: map[string]interface{}{ + Details: map[string]any{ "required": false, }, Type: "uuid", @@ -234,19 +235,19 @@ func TestUpdate(t *testing.T) { th.AssertDeepEquals(t, s.Attributes, map[string]resourcetypes.Attribute{ "enabled": { Type: "bool", - Details: map[string]interface{}{ + Details: map[string]any{ "required": true, }, }, "parent_id": { Type: "uuid", - Details: map[string]interface{}{ + Details: map[string]any{ "required": false, }, }, "name": { Type: "string", - Details: map[string]interface{}{ + Details: map[string]any{ "required": true, "min_length": float64(0), "max_length": float64(128), diff --git a/gnocchi/metric/v1/status/testing/requests_test.go b/gnocchi/metric/v1/status/testing/requests_test.go index 021cc5b..3a056e4 100644 --- a/gnocchi/metric/v1/status/testing/requests_test.go +++ b/gnocchi/metric/v1/status/testing/requests_test.go @@ -22,7 +22,7 @@ func TestGetWithDetails(t *testing.T) { w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - fmt.Fprintf(w, StatusGetWithDetailsResult) + fmt.Fprint(w, StatusGetWithDetailsResult) }) details := true @@ -48,7 +48,7 @@ func TestGetWithoutDetails(t *testing.T) { w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - fmt.Fprintf(w, StatusGetWithoutDetailsResult) + fmt.Fprint(w, StatusGetWithoutDetailsResult) }) details := false diff --git a/internal/testing/util_test.go b/internal/testing/util_test.go index 064a905..c233e72 100644 --- a/internal/testing/util_test.go +++ b/internal/testing/util_test.go @@ -17,7 +17,7 @@ func TestRemainingKeys(t *testing.T) { IsAdmin bool } - userResponse := map[string]interface{}{ + userResponse := map[string]any{ "user_id": "abcd1234", "username": "jdoe", "location": "Hawaii", @@ -27,7 +27,7 @@ func TestRemainingKeys(t *testing.T) { "custom_field": "foo", } - expected := map[string]interface{}{ + expected := map[string]any{ "created_at": "2017-06-08T02:49:03.000000", "is_admin": "true", "custom_field": "foo", diff --git a/internal/util.go b/internal/util.go index 029c701..5c0c61f 100644 --- a/internal/util.go +++ b/internal/util.go @@ -5,6 +5,7 @@ import ( "crypto/tls" "crypto/x509" "fmt" + "maps" "os" "os/user" "path/filepath" @@ -18,11 +19,9 @@ import ( // // This is useful for determining the extra fields returned in response bodies // for resources that can contain an arbitrary or dynamic number of fields. -func RemainingKeys(s interface{}, m map[string]interface{}) (extras map[string]interface{}) { - extras = make(map[string]interface{}) - for k, v := range m { - extras[k] = v - } +func RemainingKeys(s any, m map[string]any) (extras map[string]any) { + extras = make(map[string]any) + maps.Copy(extras, m) valueOf := reflect.ValueOf(s) typeOf := reflect.TypeOf(s) @@ -44,14 +43,14 @@ func RemainingKeys(s interface{}, m map[string]interface{}) (extras map[string]i func PrepareTLSConfig(caCertFile, clientCertFile, clientKeyFile string, insecure *bool) (*tls.Config, error) { config := &tls.Config{} if caCertFile != "" { - caCert, _, err := pathOrContents(caCertFile) + caCert, err := pathOrContents(caCertFile) if err != nil { - return nil, fmt.Errorf("Error reading CA Cert: %s", err) + return nil, fmt.Errorf("error reading CA Cert: %s", err) } caCertPool := x509.NewCertPool() if ok := caCertPool.AppendCertsFromPEM(bytes.TrimSpace(caCert)); !ok { - return nil, fmt.Errorf("Error parsing CA Cert from %s", caCertFile) + return nil, fmt.Errorf("error parsing CA Cert from %s", caCertFile) } config.RootCAs = caCertPool } @@ -63,13 +62,13 @@ func PrepareTLSConfig(caCertFile, clientCertFile, clientKeyFile string, insecure } if clientCertFile != "" && clientKeyFile != "" { - clientCert, _, err := pathOrContents(clientCertFile) + clientCert, err := pathOrContents(clientCertFile) if err != nil { - return nil, fmt.Errorf("Error reading Client Cert: %s", err) + return nil, fmt.Errorf("error reading Client Cert: %s", err) } - clientKey, _, err := pathOrContents(clientKeyFile) + clientKey, err := pathOrContents(clientKeyFile) if err != nil { - return nil, fmt.Errorf("Error reading Client Key: %s", err) + return nil, fmt.Errorf("error reading Client Key: %s", err) } cert, err := tls.X509KeyPair(clientCert, clientKey) @@ -78,22 +77,21 @@ func PrepareTLSConfig(caCertFile, clientCertFile, clientKeyFile string, insecure } config.Certificates = []tls.Certificate{cert} - config.BuildNameToCertificate() } return config, nil } -func pathOrContents(poc string) ([]byte, bool, error) { +func pathOrContents(poc string) ([]byte, error) { if len(poc) == 0 { - return nil, false, nil + return nil, nil } path := poc if path[0] == '~' { usr, err := user.Current() if err != nil { - return []byte(path), true, err + return []byte(path), err } if len(path) == 1 { @@ -106,10 +104,10 @@ func pathOrContents(poc string) ([]byte, bool, error) { if _, err := os.Stat(path); err == nil { contents, err := os.ReadFile(path) if err != nil { - return contents, true, err + return contents, err } - return contents, true, nil + return contents, nil } - return []byte(poc), false, nil + return []byte(poc), nil } diff --git a/openstack/baremetal/v1/nodes/configdrive.go b/openstack/baremetal/v1/nodes/configdrive.go index aeaf53a..b0cc2bf 100644 --- a/openstack/baremetal/v1/nodes/configdrive.go +++ b/openstack/baremetal/v1/nodes/configdrive.go @@ -3,18 +3,17 @@ package nodes import ( "encoding/base64" "encoding/json" - "io/ioutil" "os" "path/filepath" ) // A ConfigDrive struct will be used to create a base64-encoded, gzipped ISO9660 image for use with Ironic. type ConfigDrive struct { - UserData UserDataBuilder `json:"user_data"` - MetaData map[string]interface{} `json:"meta_data"` - NetworkData map[string]interface{} `json:"network_data"` - Version string `json:"-"` - BuildDirectory string `json:"-"` + UserData UserDataBuilder `json:"user_data"` + MetaData map[string]any `json:"meta_data"` + NetworkData map[string]any `json:"network_data"` + Version string `json:"-"` + BuildDirectory string `json:"-"` } // Interface to let us specify a raw string, or a map for the user data @@ -22,7 +21,7 @@ type UserDataBuilder interface { ToUserData() ([]byte, error) } -type UserDataMap map[string]interface{} +type UserDataMap map[string]any type UserDataString string // Converts a UserDataMap to JSON-string @@ -41,7 +40,7 @@ type ConfigDriveBuilder interface { // Writes out a ConfigDrive to a temporary directory, and returns the path func (configDrive ConfigDrive) ToDirectory() (string, error) { // Create a temporary directory for our config drive - directory, err := ioutil.TempDir(configDrive.BuildDirectory, "gophercloud") + directory, err := os.MkdirTemp(configDrive.BuildDirectory, "gophercloud") if err != nil { return "", err } @@ -67,7 +66,7 @@ func (configDrive ConfigDrive) ToDirectory() (string, error) { return "", err } - if err := ioutil.WriteFile(userDataPath, data, 0644); err != nil { + if err := os.WriteFile(userDataPath, data, 0644); err != nil { return "", err } } @@ -80,7 +79,7 @@ func (configDrive ConfigDrive) ToDirectory() (string, error) { return "", err } - if err := ioutil.WriteFile(metaDataPath, data, 0644); err != nil { + if err := os.WriteFile(metaDataPath, data, 0644); err != nil { return "", err } } @@ -93,7 +92,7 @@ func (configDrive ConfigDrive) ToDirectory() (string, error) { return "", err } - if err := ioutil.WriteFile(networkDataPath, data, 0644); err != nil { + if err := os.WriteFile(networkDataPath, data, 0644); err != nil { return "", err } } diff --git a/openstack/baremetal/v1/nodes/doc.go b/openstack/baremetal/v1/nodes/doc.go index 1f8b31f..b7f2a23 100644 --- a/openstack/baremetal/v1/nodes/doc.go +++ b/openstack/baremetal/v1/nodes/doc.go @@ -15,8 +15,8 @@ For example: "ignition": map[string]string{ "version": "2.2.0", }, - "systemd": map[string]interface{}{ - "units": []map[string]interface{}{{ + "systemd": map[string]any{ + "units": []map[string]any{{ "name": "example.service", "enabled": true, }, diff --git a/openstack/baremetal/v1/nodes/testing/configdrive_test.go b/openstack/baremetal/v1/nodes/testing/configdrive_test.go index 3085e27..f0fab95 100644 --- a/openstack/baremetal/v1/nodes/testing/configdrive_test.go +++ b/openstack/baremetal/v1/nodes/testing/configdrive_test.go @@ -1,7 +1,6 @@ package testing import ( - "io/ioutil" "os" "path/filepath" "testing" @@ -30,15 +29,15 @@ func TestConfigDriveToDirectory(t *testing.T) { basePath := filepath.FromSlash(path + "/openstack/latest") - userData, err := ioutil.ReadFile(filepath.FromSlash(basePath + "/user_data")) + userData, err := os.ReadFile(filepath.FromSlash(basePath + "/user_data")) th.AssertNoErr(t, err) th.CheckJSONEquals(t, string(userData), IgnitionUserData) - metaData, err := ioutil.ReadFile(filepath.FromSlash(basePath + "/meta_data.json")) + metaData, err := os.ReadFile(filepath.FromSlash(basePath + "/meta_data.json")) th.AssertNoErr(t, err) th.CheckJSONEquals(t, string(metaData), OpenStackMetaData) - networkData, err := ioutil.ReadFile(filepath.FromSlash(basePath + "/network_data.json")) + networkData, err := os.ReadFile(filepath.FromSlash(basePath + "/network_data.json")) th.AssertNoErr(t, err) th.CheckJSONEquals(t, string(networkData), NetworkData) } @@ -50,15 +49,15 @@ func TestConfigDriveVersionToDirectory(t *testing.T) { basePath := filepath.FromSlash(path + "/openstack/" + ConfigDriveVersioned.Version) - userData, err := ioutil.ReadFile(filepath.FromSlash(basePath + "/user_data")) + userData, err := os.ReadFile(filepath.FromSlash(basePath + "/user_data")) th.AssertNoErr(t, err) th.CheckJSONEquals(t, string(userData), IgnitionUserData) - metaData, err := ioutil.ReadFile(filepath.FromSlash(basePath + "/meta_data.json")) + metaData, err := os.ReadFile(filepath.FromSlash(basePath + "/meta_data.json")) th.AssertNoErr(t, err) th.CheckJSONEquals(t, string(metaData), OpenStackMetaData) - networkData, err := ioutil.ReadFile(filepath.FromSlash(basePath + "/network_data.json")) + networkData, err := os.ReadFile(filepath.FromSlash(basePath + "/network_data.json")) th.AssertNoErr(t, err) th.CheckJSONEquals(t, string(networkData), NetworkData) } diff --git a/openstack/baremetal/v1/nodes/testing/fixtures.go b/openstack/baremetal/v1/nodes/testing/fixtures.go index cb8f6b7..583a0c6 100644 --- a/openstack/baremetal/v1/nodes/testing/fixtures.go +++ b/openstack/baremetal/v1/nodes/testing/fixtures.go @@ -54,8 +54,8 @@ var ( "ignition": map[string]string{ "version": "2.2.0", }, - "systemd": map[string]interface{}{ - "units": []map[string]interface{}{{ + "systemd": map[string]any{ + "units": []map[string]any{{ "name": "example.service", "enabled": true, }, @@ -63,7 +63,7 @@ var ( }, } - OpenStackMetaData = map[string]interface{}{ + OpenStackMetaData = map[string]any{ "availability_zone": "nova", "hostname": "test.novalocal", "public_keys": map[string]string{ @@ -71,7 +71,7 @@ var ( }, } - NetworkData = map[string]interface{}{ + NetworkData = map[string]any{ "services": []map[string]string{ { "type": "dns", diff --git a/openstack/baremetal/v1/nodes/util.go b/openstack/baremetal/v1/nodes/util.go index d5c63ac..1f81406 100644 --- a/openstack/baremetal/v1/nodes/util.go +++ b/openstack/baremetal/v1/nodes/util.go @@ -4,7 +4,6 @@ import ( "bytes" "compress/gzip" "fmt" - "io/ioutil" "os" "os/exec" ) @@ -14,7 +13,7 @@ func GzipFile(path string) ([]byte, error) { var buf bytes.Buffer w := gzip.NewWriter(&buf) - contents, err := ioutil.ReadFile(path) + contents, err := os.ReadFile(path) if err != nil { return nil, err } @@ -34,7 +33,7 @@ func GzipFile(path string) ([]byte, error) { // Packs a directory into a gzipped ISO image func PackDirectoryAsISO(path string) ([]byte, error) { - iso, err := ioutil.TempFile("", "gophercloud-iso") + iso, err := os.CreateTemp("", "gophercloud-iso") if err != nil { return nil, err } diff --git a/openstack/clientconfig/requests.go b/openstack/clientconfig/requests.go index f334774..606bd81 100644 --- a/openstack/clientconfig/requests.go +++ b/openstack/clientconfig/requests.go @@ -254,7 +254,7 @@ func GetCloudFromYAML(opts *ClientOpts) (*Cloud, error) { cloud, err = mergeClouds(cloud, publicCloud) if err != nil { - return nil, fmt.Errorf("Could not merge information from clouds.yaml and clouds-public.yaml for cloud %s", profileName) + return nil, fmt.Errorf("could not merge information from clouds.yaml and clouds-public.yaml for cloud %s", profileName) } } } @@ -282,7 +282,7 @@ func GetCloudFromYAML(opts *ClientOpts) (*Cloud, error) { // if no entry in clouds.yaml was found and // if a single-entry secureCloud wasn't used. // At this point, no entry could be determined at all. - return nil, fmt.Errorf("Could not find cloud %s", cloudName) + return nil, fmt.Errorf("could not find cloud %s", cloudName) } // If secureCloud has content and it differs from the cloud entry, @@ -298,7 +298,7 @@ func GetCloudFromYAML(opts *ClientOpts) (*Cloud, error) { // As an extra precaution, do one final check to see if cloud is nil. // We shouldn't reach this point, though. if cloud == nil { - return nil, fmt.Errorf("Could not find cloud %s", cloudName) + return nil, fmt.Errorf("could not find cloud %s", cloudName) } // Default is to verify SSL API requests @@ -402,7 +402,7 @@ func AuthOptions(opts *ClientOpts) (*gophercloud.AuthOptions, error) { return v3auth(cloud, opts) } - return nil, fmt.Errorf("Unable to build AuthOptions") + return nil, fmt.Errorf("unable to build AuthOptions") } func determineIdentityAPI(cloud *Cloud, opts *ClientOpts) string { diff --git a/openstack/clientconfig/results.go b/openstack/clientconfig/results.go index 6f3bd11..5a04e7d 100644 --- a/openstack/clientconfig/results.go +++ b/openstack/clientconfig/results.go @@ -168,7 +168,7 @@ func (r *Region) UnmarshalJSON(data []byte) error { // UnmarshalYAML handles either a plain string acting as the Name property or // a struct, mimicking the Python-based openstacksdk. -func (r *Region) UnmarshalYAML(unmarshal func(interface{}) error) error { +func (r *Region) UnmarshalYAML(unmarshal func(any) error) error { var name string if err := unmarshal(&name); err == nil { r.Name = name diff --git a/openstack/clientconfig/utils.go b/openstack/clientconfig/utils.go index ec8a77a..6eece9f 100644 --- a/openstack/clientconfig/utils.go +++ b/openstack/clientconfig/utils.go @@ -3,7 +3,6 @@ package clientconfig import ( "encoding/json" "fmt" - "io/ioutil" "os" "os/user" "path/filepath" @@ -24,7 +23,7 @@ func defaultIfEmpty(value string, defaultValue string) string { // mergeCLouds merges two Clouds recursively (the AuthInfo also gets merged). // In case both Clouds define a value, the value in the 'override' cloud takes precedence -func mergeClouds(override, cloud interface{}) (*Cloud, error) { +func mergeClouds(override, cloud any) (*Cloud, error) { overrideJson, err := json.Marshal(override) if err != nil { return nil, err @@ -33,12 +32,12 @@ func mergeClouds(override, cloud interface{}) (*Cloud, error) { if err != nil { return nil, err } - var overrideInterface interface{} + var overrideInterface any err = json.Unmarshal(overrideJson, &overrideInterface) if err != nil { return nil, err } - var cloudInterface interface{} + var cloudInterface any err = json.Unmarshal(cloudJson, &cloudInterface) if err != nil { return nil, err @@ -58,10 +57,10 @@ func mergeClouds(override, cloud interface{}) (*Cloud, error) { // merges two interfaces. In cases where a value is defined for both 'overridingInterface' and // 'inferiorInterface' the value in 'overridingInterface' will take precedence. -func mergeInterfaces(overridingInterface, inferiorInterface interface{}) interface{} { +func mergeInterfaces(overridingInterface, inferiorInterface any) any { switch overriding := overridingInterface.(type) { - case map[string]interface{}: - interfaceMap, ok := inferiorInterface.(map[string]interface{}) + case map[string]any: + interfaceMap, ok := inferiorInterface.(map[string]any) if !ok { return overriding } @@ -72,18 +71,16 @@ func mergeInterfaces(overridingInterface, inferiorInterface interface{}) interfa overriding[k] = v } } - case []interface{}: - list, ok := inferiorInterface.([]interface{}) + case []any: + list, ok := inferiorInterface.([]any) if !ok { return overriding } - for i := range list { - overriding = append(overriding, list[i]) - } + overriding = append(overriding, list...) return overriding case nil: // mergeClouds(nil, map[string]interface{...}) -> map[string]interface{...} - v, ok := inferiorInterface.(map[string]interface{}) + v, ok := inferiorInterface.(map[string]any) if ok { return v } @@ -109,7 +106,7 @@ func FindAndReadCloudsYAML() (string, []byte, error) { // OS_CLIENT_CONFIG_FILE if v := env.Getenv("OS_CLIENT_CONFIG_FILE"); v != "" { if ok := fileExists(v); ok { - content, err := ioutil.ReadFile(v) + content, err := os.ReadFile(v) return v, content, err } } @@ -146,7 +143,7 @@ func FindAndReadYAML(yamlFile string) (string, []byte, error) { filename := filepath.Join(cwd, yamlFile) if ok := fileExists(filename); ok { - content, err := ioutil.ReadFile(filename) + content, err := os.ReadFile(filename) return filename, content, err } @@ -156,7 +153,7 @@ func FindAndReadYAML(yamlFile string) (string, []byte, error) { if homeDir != "" { filename := filepath.Join(homeDir, ".config/openstack/"+yamlFile) if ok := fileExists(filename); ok { - content, err := ioutil.ReadFile(filename) + content, err := os.ReadFile(filename) return filename, content, err } } @@ -165,7 +162,7 @@ func FindAndReadYAML(yamlFile string) (string, []byte, error) { // unix-specific site config directory: /etc/openstack. filename = "/etc/openstack/" + yamlFile if ok := fileExists(filename); ok { - content, err := ioutil.ReadFile(filename) + content, err := os.ReadFile(filename) return filename, content, err } diff --git a/openstack/helpers/projectpurge.go b/openstack/helpers/projectpurge.go index d41e0c5..2b06c5c 100644 --- a/openstack/helpers/projectpurge.go +++ b/openstack/helpers/projectpurge.go @@ -72,19 +72,19 @@ func ProjectPurgeCompute(ctx context.Context, projectID string, purgeOpts Comput allPages, err := servers.List(purgeOpts.Client, listOpts).AllPages(ctx) if err != nil { - return fmt.Errorf("Error finding servers for project: " + projectID) + return fmt.Errorf("error finding servers for project: %s", projectID) } allServers, err := servers.ExtractServers(allPages) if err != nil { - return fmt.Errorf("Error extracting servers for project: " + projectID) + return fmt.Errorf("error extracting servers for project: %s", projectID) } if len(allServers) > 0 { for _, server := range allServers { err = servers.Delete(ctx, purgeOpts.Client, server.ID).ExtractErr() if err != nil { - return fmt.Errorf("Error deleting server: " + server.Name + " from project: " + projectID) + return fmt.Errorf("error deleting server: %s from project: %s", server.Name, projectID) } } } @@ -148,11 +148,11 @@ func clearBlockStorageVolumes(ctx context.Context, projectID string, storageClie } allPages, err := volumes.List(storageClient, listOpts).AllPages(ctx) if err != nil { - return fmt.Errorf("Error finding volumes for project: " + projectID) + return fmt.Errorf("error finding volumes for project: %s", projectID) } allVolumes, err := volumes.ExtractVolumes(allPages) if err != nil { - return fmt.Errorf("Error extracting volumes for project: " + projectID) + return fmt.Errorf("error extracting volumes for project: %s", projectID) } if len(allVolumes) > 0 { deleteOpts := volumes.DeleteOpts{ @@ -161,7 +161,7 @@ func clearBlockStorageVolumes(ctx context.Context, projectID string, storageClie for _, volume := range allVolumes { err = volumes.Delete(ctx, storageClient, volume.ID, deleteOpts).ExtractErr() if err != nil { - return fmt.Errorf("Error deleting volume: " + volume.Name + " from project: " + projectID) + return fmt.Errorf("error deleting volume: %s from project: %s", volume.Name, projectID) } } } @@ -176,17 +176,17 @@ func clearBlockStorageSnaphosts(ctx context.Context, projectID string, storageCl } allPages, err := snapshots.List(storageClient, listOpts).AllPages(ctx) if err != nil { - return fmt.Errorf("Error finding snapshots for project: " + projectID) + return fmt.Errorf("error finding snapshots for project: %s", projectID) } allSnapshots, err := snapshots.ExtractSnapshots(allPages) if err != nil { - return fmt.Errorf("Error extracting snapshots for project: " + projectID) + return fmt.Errorf("error extracting snapshots for project: %s", projectID) } if len(allSnapshots) > 0 { for _, snaphost := range allSnapshots { err = snapshots.Delete(ctx, storageClient, snaphost.ID).ExtractErr() if err != nil { - return fmt.Errorf("Error deleting snaphost: " + snaphost.Name + " from project: " + projectID) + return fmt.Errorf("error deleting snaphost: %s from project: %s", snaphost.Name, projectID) } } } @@ -207,7 +207,7 @@ func clearPortforwarding(ctx context.Context, networkClient *gophercloud.Service for _, pf := range allPFs { err := portforwarding.Delete(ctx, networkClient, fipID, pf.ID).ExtractErr() if err != nil { - return fmt.Errorf("Error deleting floating IP port forwarding: " + pf.ID + " from project: " + projectID) + return fmt.Errorf("error deleting floating IP port forwarding: %s from project %s", pf.ID, projectID) } } @@ -220,11 +220,11 @@ func clearNetworkingFloatingIPs(ctx context.Context, projectID string, networkCl } allPages, err := floatingips.List(networkClient, listOpts).AllPages(ctx) if err != nil { - return fmt.Errorf("Error finding floating IPs for project: " + projectID) + return fmt.Errorf("error finding floating IPs for project: %s", projectID) } allFloatings, err := floatingips.ExtractFloatingIPs(allPages) if err != nil { - return fmt.Errorf("Error extracting floating IPs for project: " + projectID) + return fmt.Errorf("error extracting floating IPs for project: %s", projectID) } if len(allFloatings) > 0 { for _, floating := range allFloatings { @@ -236,7 +236,7 @@ func clearNetworkingFloatingIPs(ctx context.Context, projectID string, networkCl err = floatingips.Delete(ctx, networkClient, floating.ID).ExtractErr() if err != nil { - return fmt.Errorf("Error deleting floating IP: " + floating.ID + " from project: " + projectID) + return fmt.Errorf("error deleting floating IP: %s from project: %s", floating.ID, projectID) } } } @@ -251,11 +251,11 @@ func clearNetworkingPorts(ctx context.Context, projectID string, networkClient * allPages, err := ports.List(networkClient, listOpts).AllPages(ctx) if err != nil { - return fmt.Errorf("Error finding ports for project: " + projectID) + return fmt.Errorf("error finding ports for project: %s", projectID) } allPorts, err := ports.ExtractPorts(allPages) if err != nil { - return fmt.Errorf("Error extracting ports for project: " + projectID) + return fmt.Errorf("error extracting ports for project: %s", projectID) } if len(allPorts) > 0 { for _, port := range allPorts { @@ -265,7 +265,7 @@ func clearNetworkingPorts(ctx context.Context, projectID string, networkClient * err = ports.Delete(ctx, networkClient, port.ID).ExtractErr() if err != nil { - return fmt.Errorf("Error deleting port: " + port.ID + " from project: " + projectID) + return fmt.Errorf("error deleting port: %s from project: %s", port.ID, projectID) } } } @@ -282,11 +282,11 @@ func getAllSubnets(ctx context.Context, projectID string, networkClient *gopherc allPages, err := networks.List(networkClient, listOpts).AllPages(ctx) if err != nil { - return subnets, fmt.Errorf("Error finding networks for project: " + projectID) + return subnets, fmt.Errorf("error finding networks for project: %s", projectID) } allNetworks, err := networks.ExtractNetworks(allPages) if err != nil { - return subnets, fmt.Errorf("Error extracting networks for project: " + projectID) + return subnets, fmt.Errorf("error extracting networks for project: %s", projectID) } if len(allNetworks) > 0 { for _, network := range allNetworks { @@ -297,7 +297,7 @@ func getAllSubnets(ctx context.Context, projectID string, networkClient *gopherc return subnets, nil } -func clearAllRouterInterfaces(ctx context.Context, projectID string, routerID string, subnets []string, networkClient *gophercloud.ServiceClient) error { +func clearAllRouterInterfaces(ctx context.Context, routerID string, subnets []string, networkClient *gophercloud.ServiceClient) error { for _, subnet := range subnets { intOpts := routers.RemoveInterfaceOpts{ SubnetID: subnet, @@ -318,21 +318,21 @@ func clearNetworkingRouters(ctx context.Context, projectID string, networkClient } allPages, err := routers.List(networkClient, listOpts).AllPages(ctx) if err != nil { - return fmt.Errorf("Error finding routers for project: " + projectID) + return fmt.Errorf("error finding routers for project: %s", projectID) } allRouters, err := routers.ExtractRouters(allPages) if err != nil { - return fmt.Errorf("Error extracting routers for project: " + projectID) + return fmt.Errorf("error extracting routers for project: %s", projectID) } subnets, err := getAllSubnets(ctx, projectID, networkClient) if err != nil { - return fmt.Errorf("Error fetching subnets project: " + projectID) + return fmt.Errorf("error fetching subnets project: %s", projectID) } if len(allRouters) > 0 { for _, router := range allRouters { - err = clearAllRouterInterfaces(ctx, projectID, router.ID, subnets, networkClient) + err = clearAllRouterInterfaces(ctx, router.ID, subnets, networkClient) if err != nil { return err } @@ -345,12 +345,12 @@ func clearNetworkingRouters(ctx context.Context, projectID string, networkClient _, err := routers.Update(ctx, networkClient, router.ID, updateOpts).Extract() if err != nil { - return fmt.Errorf("Error deleting router: " + router.Name + " from project: " + projectID) + return fmt.Errorf("error deleting router: %s from project: %s", router.Name, projectID) } err = routers.Delete(ctx, networkClient, router.ID).ExtractErr() if err != nil { - return fmt.Errorf("Error deleting router: " + router.Name + " from project: " + projectID) + return fmt.Errorf("error deleting router: %s from project: %s", router.Name, projectID) } } } @@ -365,17 +365,17 @@ func clearNetworkingNetworks(ctx context.Context, projectID string, networkClien allPages, err := networks.List(networkClient, listOpts).AllPages(ctx) if err != nil { - return fmt.Errorf("Error finding networks for project: " + projectID) + return fmt.Errorf("error finding networks for project: %s", projectID) } allNetworks, err := networks.ExtractNetworks(allPages) if err != nil { - return fmt.Errorf("Error extracting networks for project: " + projectID) + return fmt.Errorf("error extracting networks for project: %s", projectID) } if len(allNetworks) > 0 { for _, network := range allNetworks { err = networks.Delete(ctx, networkClient, network.ID).ExtractErr() if err != nil { - return fmt.Errorf("Error deleting network: " + network.Name + " from project: " + projectID) + return fmt.Errorf("error deleting network: %s from project: %s", network.Name, projectID) } } } @@ -389,17 +389,17 @@ func clearNetworkingSecurityGroups(ctx context.Context, projectID string, networ } allPages, err := groups.List(networkClient, listOpts).AllPages(ctx) if err != nil { - return fmt.Errorf("Error finding security groups for project: " + projectID) + return fmt.Errorf("error finding security groups for project: %s", projectID) } allSecGroups, err := groups.ExtractGroups(allPages) if err != nil { - return fmt.Errorf("Error extracting security groups for project: " + projectID) + return fmt.Errorf("error extracting security groups for project: %s", projectID) } if len(allSecGroups) > 0 { for _, group := range allSecGroups { err = groups.Delete(ctx, networkClient, group.ID).ExtractErr() if err != nil { - return fmt.Errorf("Error deleting security group: " + group.Name + " from project: " + projectID) + return fmt.Errorf("error deleting security group: %s from project: %s", group.Name, projectID) } } } diff --git a/openstack/objectstorage/v1/objects/download.go b/openstack/objectstorage/v1/objects/download.go index 30b200d..540bd92 100644 --- a/openstack/objectstorage/v1/objects/download.go +++ b/openstack/objectstorage/v1/objects/download.go @@ -273,9 +273,7 @@ func downloadObject(ctx context.Context, client *gophercloud.ServiceClient, cont return nil, fmt.Errorf("error creating directory %s: %s", objectPath, err) } } else { - mkdir := !(opts.NoDownload || opts.OutFile == "") - - if mkdir { + if !opts.NoDownload && opts.OutFile != "" { dir := filepath.Dir(objectPath) if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) { if err := os.MkdirAll(dir, 0777); err != nil { diff --git a/openstack/objectstorage/v1/objects/testing/fixtures.go b/openstack/objectstorage/v1/objects/testing/fixtures.go index 0781269..ef99cfe 100644 --- a/openstack/objectstorage/v1/objects/testing/fixtures.go +++ b/openstack/objectstorage/v1/objects/testing/fixtures.go @@ -71,6 +71,6 @@ func HandleDownloadManifestSuccessfully(t *testing.T) { th.TestHeader(t, r, "Accept", "application/json") w.Header().Set("Date", "Wed, 10 Nov 2009 23:00:00 GMT") w.WriteHeader(http.StatusOK) - fmt.Fprintf(w, multipartManifest) + fmt.Fprint(w, multipartManifest) }) } diff --git a/openstack/objectstorage/v1/objects/upload.go b/openstack/objectstorage/v1/objects/upload.go index 13e9e58..1d85045 100644 --- a/openstack/objectstorage/v1/objects/upload.go +++ b/openstack/objectstorage/v1/objects/upload.go @@ -7,7 +7,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "net/http" "net/url" "os" @@ -224,14 +223,14 @@ func Upload(ctx context.Context, client *gophercloud.ServiceClient, containerNam if sourceFileInfo.IsDir() { // If the source path is a directory, then create a Directory Marker, // even if DirMarker wasn't specified. - return createDirMarker(ctx, client, containerName, objectName, opts, origObject, sourceFileInfo) + return createDirMarker(ctx, client, containerName, objectName, opts, origObject) } return uploadObject(ctx, client, containerName, objectName, opts, origObject, sourceFileInfo) } if opts.DirMarker { - return createDirMarker(ctx, client, containerName, objectName, opts, origObject, sourceFileInfo) + return createDirMarker(ctx, client, containerName, objectName, opts, origObject) } // Finally, create an empty object. @@ -248,8 +247,7 @@ func createDirMarker( containerName string, objectName string, opts *UploadOpts, - origObject *originalObject, - sourceFileInfo os.FileInfo) (*UploadResult, error) { + origObject *originalObject) (*UploadResult, error) { uploadResult := &UploadResult{ Action: "create_dir_marker", @@ -529,7 +527,7 @@ func uploadObject( } if !uploadSegmentResult.Success { - return nil, fmt.Errorf("Problem uploading segment %d of %s/%s", segIndex, containerName, objectName) + return nil, fmt.Errorf("problem uploading segment %d of %s/%s", segIndex, containerName, objectName) } if uploadSegmentResult.Size != 0 { @@ -603,14 +601,17 @@ func uploadObject( // Wrap it in a NewReader to prevent the Transport // from doing this. if readSeeker, ok := opts.Content.(io.ReadSeeker); ok { - data, err := ioutil.ReadAll(readSeeker) + data, err := io.ReadAll(readSeeker) if err != nil { return nil, err } contentLength = int64(len(data)) readSeeker = bytes.NewReader(data) - readSeeker.Seek(0, io.SeekStart) + _, err = readSeeker.Seek(0, io.SeekStart) + if err != nil { + return nil, err + } reader = readSeeker } else { reader = opts.Content @@ -623,7 +624,7 @@ func uploadObject( // chance that this can exhaust memory on very large streams. readSeeker, isReadSeeker := reader.(io.ReadSeeker) if !isReadSeeker { - data, err := ioutil.ReadAll(reader) + data, err := io.ReadAll(reader) if err != nil { return nil, err } @@ -635,7 +636,10 @@ func uploadObject( return nil, err } - readSeeker.Seek(0, io.SeekStart) + _, err := readSeeker.Seek(0, io.SeekStart) + if err != nil { + return nil, err + } reader = readSeeker eTag = fmt.Sprintf("%x", hash.Sum(nil)) @@ -690,9 +694,7 @@ func uploadObject( return nil, err } - for _, o := range allObjects { - oldObjects = append(oldObjects, o) - } + oldObjects = append(oldObjects, allObjects...) delObjectMap[sContainer] = oldObjects } @@ -819,7 +821,7 @@ func uploadSegment(ctx context.Context, client *gophercloud.ServiceClient, opts if opts.Checksum { if createHeader.ETag != eTag { - err := fmt.Errorf("Segment %d: upload verification failed: md5 mismatch, local %s != remote %s", opts.SegmentIndex, eTag, createHeader.ETag) + err := fmt.Errorf("segment %d: upload verification failed: md5 mismatch, local %s != remote %s", opts.SegmentIndex, eTag, createHeader.ETag) return nil, err } }