diff --git a/.github/workflows/e2e-olm.yml b/.github/workflows/e2e-olm.yml index 176043e..23aef3c 100644 --- a/.github/workflows/e2e-olm.yml +++ b/.github/workflows/e2e-olm.yml @@ -57,6 +57,7 @@ jobs: kubernetes-version: - "1.27.11" - "1.28.7" + - "1.29.2" steps: - name: "Checkout" uses: actions/checkout@v4 @@ -66,7 +67,7 @@ jobs: go-version-file: 'go.mod' check-latest: true - name: 'SetUp KinD' - uses: container-tools/kind-action@v2 + uses: container-tools/kind-action@v2.0.4 with: version: "v0.22.0" kubectl_version: v${{ matrix.kubernetes-version }} diff --git a/.github/workflows/e2e-operator.yml b/.github/workflows/e2e-operator.yml index 8ca438f..06a3f94 100644 --- a/.github/workflows/e2e-operator.yml +++ b/.github/workflows/e2e-operator.yml @@ -37,6 +37,7 @@ jobs: kubernetes-version: - "1.27.11" - "1.28.7" + - "1.29.2" steps: - name: "Checkout" uses: actions/checkout@v4 @@ -46,7 +47,7 @@ jobs: go-version-file: 'go.mod' check-latest: true - name: 'SetUp KinD' - uses: container-tools/kind-action@v2 + uses: container-tools/kind-action@v2.0.4 with: version: "v0.22.0" kubectl_version: v${{ matrix.kubernetes-version }} @@ -57,15 +58,8 @@ jobs: run: | ./hack/scripts/deploy_ingress.sh - name: "SetUp Dapr Kubernetes Operator" - run: | - make deploy/e2e - - kubectl wait \ - --namespace=dapr-system \ - --for=condition=ready \ - pod \ - --selector=control-plane=dapr-control-plane \ - --timeout=90s + run: | + ./hack/scripts/deploy_e2e.sh - name: "Run Dapr Kubernetes Operator e2e" run: | make test/e2e/operator diff --git a/Dockerfile b/Dockerfile index 58ce12c..eaa4bb0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Build the manager binary -FROM golang:1.21 as builder +FROM golang:1.22 as builder ARG TARGETOS ARG TARGETARCH diff --git a/Makefile b/Makefile index 57204e5..7174c89 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ CATALOG_VERSION ?= latest CATALOG_CONTAINER_IMAGE ?= $(CONTAINER_REGISTRY)/$(CONTAINER_REGISTRY_ORG)/$(PROJECT_NAME)-catalog:$(CATALOG_VERSION) LINT_GOGC ?= 10 -LINT_DEADLINE ?= 10m +LINT_TIMEOUT ?= 10m MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) PROJECT_PATH := $(patsubst %/,%,$(dir $(MKFILE_PATH))) @@ -26,13 +26,13 @@ HELM_CHART_VERSION ?= 1.13.1 HELM_CHART_URL ?= https://raw.githubusercontent.com/dapr/helm-charts/master/dapr-$(HELM_CHART_VERSION).tgz ## Tool Versions -CODEGEN_VERSION ?= v0.28.3 -KUSTOMIZE_VERSION ?= v5.2.1 -CONTROLLER_TOOLS_VERSION ?= v0.13.0 -KIND_VERSION ?= v0.20.0 -LINTER_VERSION ?= v1.55.1 -OPERATOR_SDK_VERSION ?= v1.32.0 -OPM_VERSION ?= v1.30.1 +CODEGEN_VERSION ?= v0.28.8 +KUSTOMIZE_VERSION ?= v5.3.0 +CONTROLLER_TOOLS_VERSION ?= v0.14.0 +KIND_VERSION ?= v0.22.0 +LINTER_VERSION ?= v1.57.2 +OPERATOR_SDK_VERSION ?= v1.34.1 +OPM_VERSION ?= v1.38.0 GOVULNCHECK_VERSION ?= latest ## Tool Binaries @@ -164,8 +164,8 @@ check/lint: golangci-lint @$(LINTER) run \ --config .golangci.yml \ --out-format tab \ - --skip-dirs etc \ - --deadline $(LINT_DEADLINE) \ + --exclude-dirs etc \ + --timeout $(LINT_TIMEOUT) \ --verbose .PHONY: check/lint/fix @@ -173,8 +173,8 @@ check/lint/fix: golangci-lint @$(LINTER) run \ --config .golangci.yml \ --out-format tab \ - --skip-dirs etc \ - --deadline $(LINT_DEADLINE) \ + --exclude-dirs etc \ + --timeout $(LINT_TIMEOUT) \ --fix .PHONY: check/vuln diff --git a/config/crd/bases/operator.dapr.io_daprcontrolplanes.yaml b/config/crd/bases/operator.dapr.io_daprcontrolplanes.yaml index 0e801fe..6038bf7 100644 --- a/config/crd/bases/operator.dapr.io_daprcontrolplanes.yaml +++ b/config/crd/bases/operator.dapr.io_daprcontrolplanes.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.13.0 + controller-gen.kubebuilder.io/version: v0.14.0 name: daprcontrolplanes.operator.dapr.io spec: group: operator.dapr.io @@ -47,23 +47,28 @@ spec: openAPIV3Schema: properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: properties: values: - description: 'JSON represents any valid JSON value. These types are - supported: bool, int64, float64, string, []interface{}, map[string]interface{} - and nil.' + description: |- + JSON represents any valid JSON value. + These types are supported: bool, int64, float64, string, []interface{}, map[string]interface{} and nil. x-kubernetes-preserve-unknown-fields: true type: object status: @@ -80,42 +85,42 @@ spec: conditions: items: description: "Condition contains details for one aspect of the current - state of this API Resource. --- This struct is intended for direct - use as an array at the field path .status.conditions. For example, - \n type FooStatus struct{ // Represents the observations of a - foo's current state. // Known .status.conditions.type are: \"Available\", - \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge - // +listType=map // +listMapKey=type Conditions []metav1.Condition - `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" - protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" properties: lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should be when - the underlying condition changed. If that is not known, then - using the time when the API field changed is acceptable. + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. maxLength: 32768 type: string observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, if .metadata.generation - is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the current - state of the instance. + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: - description: reason contains a programmatic identifier indicating - the reason for the condition's last transition. Producers - of specific condition types may define expected values and - meanings for this field, and whether the values are considered - a guaranteed API. The value should be a CamelCase string. + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 @@ -129,11 +134,12 @@ spec: - Unknown type: string type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string diff --git a/config/crd/bases/operator.dapr.io_daprcruiscontrols.yaml b/config/crd/bases/operator.dapr.io_daprcruiscontrols.yaml index 64976d2..567056d 100644 --- a/config/crd/bases/operator.dapr.io_daprcruiscontrols.yaml +++ b/config/crd/bases/operator.dapr.io_daprcruiscontrols.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.13.0 + controller-gen.kubebuilder.io/version: v0.14.0 name: daprcruiscontrols.operator.dapr.io spec: group: operator.dapr.io @@ -45,14 +45,19 @@ spec: description: DaprCruiseControl is the Schema for the daprcruisecontrols API. properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object @@ -74,42 +79,42 @@ spec: conditions: items: description: "Condition contains details for one aspect of the current - state of this API Resource. --- This struct is intended for direct - use as an array at the field path .status.conditions. For example, - \n type FooStatus struct{ // Represents the observations of a - foo's current state. // Known .status.conditions.type are: \"Available\", - \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge - // +listType=map // +listMapKey=type Conditions []metav1.Condition - `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" - protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" properties: lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should be when - the underlying condition changed. If that is not known, then - using the time when the API field changed is acceptable. + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. maxLength: 32768 type: string observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, if .metadata.generation - is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the current - state of the instance. + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: - description: reason contains a programmatic identifier indicating - the reason for the condition's last transition. Producers - of specific condition types may define expected values and - meanings for this field, and whether the values are considered - a guaranteed API. The value should be a CamelCase string. + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 @@ -123,11 +128,12 @@ spec: - Unknown type: string type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string diff --git a/config/crd/bases/operator.dapr.io_daprinstances.yaml b/config/crd/bases/operator.dapr.io_daprinstances.yaml index 55fd8c1..2748368 100644 --- a/config/crd/bases/operator.dapr.io_daprinstances.yaml +++ b/config/crd/bases/operator.dapr.io_daprinstances.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.13.0 + controller-gen.kubebuilder.io/version: v0.14.0 name: daprinstances.operator.dapr.io spec: group: operator.dapr.io @@ -45,14 +45,19 @@ spec: description: DaprInstance is the Schema for the daprinstances API. properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object @@ -73,9 +78,9 @@ spec: type: string type: object values: - description: 'JSON represents any valid JSON value. These types are - supported: bool, int64, float64, string, []interface{}, map[string]interface{} - and nil.' + description: |- + JSON represents any valid JSON value. + These types are supported: bool, int64, float64, string, []interface{}, map[string]interface{} and nil. x-kubernetes-preserve-unknown-fields: true type: object status: @@ -93,42 +98,42 @@ spec: conditions: items: description: "Condition contains details for one aspect of the current - state of this API Resource. --- This struct is intended for direct - use as an array at the field path .status.conditions. For example, - \n type FooStatus struct{ // Represents the observations of a - foo's current state. // Known .status.conditions.type are: \"Available\", - \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge - // +listType=map // +listMapKey=type Conditions []metav1.Condition - `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" - protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" properties: lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should be when - the underlying condition changed. If that is not known, then - using the time when the API field changed is acceptable. + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. maxLength: 32768 type: string observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, if .metadata.generation - is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the current - state of the instance. + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: - description: reason contains a programmatic identifier indicating - the reason for the condition's last transition. Producers - of specific condition types may define expected values and - meanings for this field, and whether the values are considered - a guaranteed API. The value should be a CamelCase string. + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 @@ -142,11 +147,12 @@ spec: - Unknown type: string type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index 67490c3..2a7885d 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -8,5 +8,5 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization images: - name: controller - newName: ttl.sh/ed03fbe9-61d9-4ccf-a481-9d443244168f-local-0 - newTag: 1h + newName: ghcr.io/dapr-sandbox/dapr-kubernetes-operator + newTag: 0.0.4 diff --git a/go.mod b/go.mod index 7e1166e..bd6d412 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/dapr-sandbox/dapr-kubernetes-operator -go 1.21 +go 1.22 require ( github.com/go-logr/logr v1.4.1 diff --git a/hack/scripts/deploy_e2e.sh b/hack/scripts/deploy_e2e.sh new file mode 100755 index 0000000..dd8d9c6 --- /dev/null +++ b/hack/scripts/deploy_e2e.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +set -e + +make deploy/e2e + +kubectl wait \ + --namespace=dapr-system \ + --for=condition=ready \ + pod \ + --selector=control-plane=dapr-control-plane \ + --timeout=90s \ No newline at end of file diff --git a/hack/scripts/deploy_ingress.sh b/hack/scripts/deploy_ingress.sh index 5745721..52cb3b4 100755 --- a/hack/scripts/deploy_ingress.sh +++ b/hack/scripts/deploy_ingress.sh @@ -2,8 +2,12 @@ set -e +kubectl apply --server-side -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml -kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml +# it may take a while to have apply the +# resource, hence the kubectl wait may +# fail +sleep 5 kubectl wait \ --namespace=ingress-nginx \ diff --git a/pkg/utils/maputils/maps.go b/pkg/utils/maputils/maps.go index 095f28e..dbbb5d1 100644 --- a/pkg/utils/maputils/maps.go +++ b/pkg/utils/maputils/maps.go @@ -1,6 +1,7 @@ package maputils import ( + "errors" "fmt" "maps" ) @@ -25,7 +26,7 @@ func Merge(dst map[string]interface{}, source map[string]interface{}) map[string func Lookup(m map[string]interface{}, ks ...string) (interface{}, error) { if len(ks) == 0 { // degenerate input - return nil, fmt.Errorf("lookup needs at least one key") + return nil, errors.New("lookup needs at least one key") } if rval, ok := m[ks[0]]; !ok { return nil, fmt.Errorf("key not found; remaining keys: %v", ks) diff --git a/test/support/matchers/match_support.go b/test/support/matchers/match_support.go index 1e29216..c1b1888 100644 --- a/test/support/matchers/match_support.go +++ b/test/support/matchers/match_support.go @@ -11,7 +11,7 @@ func formattedMessage(comparisonMessage string, failurePath []interface{}) strin if len(failurePath) == 0 { diffMessage = "" } else { - diffMessage = fmt.Sprintf("\n\nfirst mismatched key: %s", formattedFailurePath(failurePath)) + diffMessage = "\n\nfirst mismatched key: " + formattedFailurePath(failurePath) } return fmt.Sprintf("%s%s", comparisonMessage, diffMessage) }