diff --git a/.bingo/OWNERS b/.bingo/OWNERS new file mode 100644 index 000000000..835cabe50 --- /dev/null +++ b/.bingo/OWNERS @@ -0,0 +1,2 @@ +approvers: + - ci-approvers diff --git a/.gitignore b/.gitignore index c2c4333ba..c1b590a02 100644 --- a/.gitignore +++ b/.gitignore @@ -21,8 +21,10 @@ cover.out # Release output /dist/** /operator-controller.yaml +/operator-controller-experimental.yaml /default-catalogs.yaml /install.sh +/install-experimental.sh # vendored files vendor/ @@ -42,3 +44,6 @@ site .tiltbuild/ .catalogd-tmp/ .vscode + +# Tmporary files and directories +/test/regression/convert/testdata/tmp/* diff --git a/.goreleaser.yml b/.goreleaser.yml index 3dbb37482..720014214 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -124,8 +124,10 @@ release: disable: '{{ ne .Env.ENABLE_RELEASE_PIPELINE "true" }}' mode: replace extra_files: - - glob: '{{ .Env.RELEASE_MANIFEST }}' - - glob: '{{ .Env.RELEASE_INSTALL }}' + - glob: '{{ .Env.STANDARD_RELEASE_MANIFEST }}' + - glob: '{{ .Env.STANDARD_RELEASE_INSTALL }}' + - glob: '{{ .Env.EXPERIMENTAL_RELEASE_MANIFEST }}' + - glob: '{{ .Env.EXPERIMENTAL_RELEASE_INSTALL }}' - glob: '{{ .Env.RELEASE_CATALOGS }}' header: | ## Installation diff --git a/Makefile b/Makefile index 98967ef87..48e926929 100644 --- a/Makefile +++ b/Makefile @@ -76,8 +76,10 @@ KUSTOMIZE_STANDARD_E2E_OVERLAY := config/overlays/standard-e2e KUSTOMIZE_EXPERIMENTAL_OVERLAY := config/overlays/experimental KUSTOMIZE_EXPERIMENTAL_E2E_OVERLAY := config/overlays/experimental-e2e -export RELEASE_MANIFEST := operator-controller.yaml -export RELEASE_INSTALL := install.sh +export STANDARD_RELEASE_MANIFEST := operator-controller.yaml +export STANDARD_RELEASE_INSTALL := install.sh +export EXPERIMENTAL_RELEASE_MANIFEST := operator-controller-experimental.yaml +export EXPERIMENTAL_RELEASE_INSTALL := install-experimental.sh export RELEASE_CATALOGS := default-catalogs.yaml # List of manifests that are checked in @@ -172,15 +174,9 @@ generate: $(CONTROLLER_GEN) #EXHELP Generate code containing DeepCopy, DeepCopyI $(CONTROLLER_GEN) --load-build-tags=$(GO_BUILD_TAGS) object:headerFile="hack/boilerplate.go.txt" paths="./..." .PHONY: verify -verify: k8s-pin kind-verify-versions fmt generate manifests crd-ref-docs generate-test-data #HELP Verify all generated code is up-to-date. Runs k8s-pin instead of just tidy. +verify: k8s-pin kind-verify-versions fmt generate manifests crd-ref-docs #HELP Verify all generated code is up-to-date. Runs k8s-pin instead of just tidy. git diff --exit-code -# Renders registry+v1 bundles in test/convert -# Used by CI in verify to catch regressions in the registry+v1 -> plain conversion code -.PHONY: generate-test-data -generate-test-data: - go run test/convert/generate-manifests.go - .PHONY: fix-lint fix-lint: $(GOLANGCI_LINT) #EXHELP Fix lint issues $(GOLANGCI_LINT) run --fix --build-tags $(GO_BUILD_TAGS) $(GOLANGCI_LINT_ARGS) @@ -209,7 +205,7 @@ verify-crd-compatibility: $(CRD_DIFF) manifests #SECTION Test .PHONY: test -test: manifests generate fmt lint test-unit test-e2e #HELP Run all tests. +test: manifests generate fmt lint test-unit test-e2e test-regression #HELP Run all tests. .PHONY: e2e e2e: #EXHELP Run the e2e tests. @@ -223,14 +219,14 @@ E2E_REGISTRY_NAME := docker-registry E2E_REGISTRY_NAMESPACE := operator-controller-e2e export REG_PKG_NAME := registry-operator -export LOCAL_REGISTRY_HOST := $(E2E_REGISTRY_NAME).$(E2E_REGISTRY_NAMESPACE).svc:5000 -export CLUSTER_REGISTRY_HOST := localhost:30000 +export CLUSTER_REGISTRY_HOST := $(E2E_REGISTRY_NAME).$(E2E_REGISTRY_NAMESPACE).svc:5000 +export LOCAL_REGISTRY_HOST := localhost:30000 export E2E_TEST_CATALOG_V1 := e2e/test-catalog:v1 export E2E_TEST_CATALOG_V2 := e2e/test-catalog:v2 -export CATALOG_IMG := $(LOCAL_REGISTRY_HOST)/$(E2E_TEST_CATALOG_V1) -.PHONY: test-ext-dev-e2e -test-ext-dev-e2e: $(OPERATOR_SDK) $(KUSTOMIZE) $(KIND) #HELP Run extension create, upgrade and delete tests. - test/extension-developer-e2e/setup.sh $(OPERATOR_SDK) $(CONTAINER_RUNTIME) $(KUSTOMIZE) $(KIND) $(KIND_CLUSTER_NAME) $(E2E_REGISTRY_NAMESPACE) +export CATALOG_IMG := $(CLUSTER_REGISTRY_HOST)/$(E2E_TEST_CATALOG_V1) +.PHONY: extension-developer-e2e +extension-developer-e2e: $(OPERATOR_SDK) $(KUSTOMIZE) #EXHELP Run extension create, upgrade and delete tests. + test/extension-developer-e2e/setup.sh $(OPERATOR_SDK) $(CONTAINER_RUNTIME) $(KUSTOMIZE) ${LOCAL_REGISTRY_HOST} ${CLUSTER_REGISTRY_HOST} go test -count=1 -v ./test/extension-developer-e2e/... UNIT_TEST_DIRS := $(shell go list ./... | grep -v /test/) @@ -252,6 +248,12 @@ test-unit: $(SETUP_ENVTEST) envtest-k8s-bins #HELP Run the unit tests $(UNIT_TEST_DIRS) \ -test.gocoverdir=$(COVERAGE_UNIT_DIR) +COVERAGE_REGRESSION_DIR := $(ROOT_DIR)/coverage/regression +.PHONY: test-regression +test-regression: #HELP Run regression test + rm -rf $(COVERAGE_REGRESSION_DIR) && mkdir -p $(COVERAGE_REGRESSION_DIR) + go test -count=1 -v ./test/regression/... -cover -coverprofile ${ROOT_DIR}/coverage/regression.out -test.gocoverdir=$(COVERAGE_REGRESSION_DIR) + .PHONY: image-registry E2E_REGISTRY_IMAGE=localhost/e2e-test-registry:devel image-registry: export GOOS=linux @@ -274,13 +276,15 @@ image-registry: ## Build the testdata catalog used for e2e tests and push it to test-e2e: SOURCE_MANIFEST := $(STANDARD_E2E_MANIFEST) test-e2e: KIND_CLUSTER_NAME := operator-controller-e2e test-e2e: GO_BUILD_EXTRA_FLAGS := -cover -test-e2e: run image-registry prometheus e2e e2e-metrics e2e-coverage kind-clean #HELP Run e2e test suite on local kind cluster +test-e2e: COVERAGE_NAME := e2e +test-e2e: run image-registry prometheus e2e e2e-coverage kind-clean #HELP Run e2e test suite on local kind cluster .PHONY: test-experimental-e2e test-experimental-e2e: SOURCE_MANIFEST := $(EXPERIMENTAL_E2E_MANIFEST) test-experimental-e2e: KIND_CLUSTER_NAME := operator-controller-e2e test-experimental-e2e: GO_BUILD_EXTRA_FLAGS := -cover -test-experimental-e2e: run image-registry prometheus experimental-e2e e2e e2e-metrics e2e-coverage kind-clean #HELP Run experimental e2e test suite on local kind cluster +test-experimental-e2e: COVERAGE_NAME := experimental-e2e +test-experimental-e2e: run image-registry prometheus experimental-e2e e2e e2e-coverage kind-clean #HELP Run experimental e2e test suite on local kind cluster .PHONY: prometheus prometheus: PROMETHEUS_NAMESPACE := olmv1-system @@ -288,20 +292,14 @@ prometheus: PROMETHEUS_VERSION := v0.83.0 prometheus: #EXHELP Deploy Prometheus into specified namespace ./hack/test/install-prometheus.sh $(PROMETHEUS_NAMESPACE) $(PROMETHEUS_VERSION) $(KUSTOMIZE) $(VERSION) -# The output alerts.out file contains any alerts, pending or firing, collected during a test run in json format. -.PHONY: e2e-metrics -e2e-metrics: ALERTS_FILE_PATH := $(if $(ARTIFACT_PATH),$(ARTIFACT_PATH),.)/alerts.out -e2e-metrics: #EXHELP Request metrics from prometheus; place in ARTIFACT_PATH if set - curl -X GET http://localhost:30900/api/v1/alerts | jq 'if (.data.alerts | length) > 0 then .data.alerts.[] else empty end' > $(ALERTS_FILE_PATH) - -.PHONY: extension-developer-e2e -extension-developer-e2e: KIND_CLUSTER_NAME := operator-controller-ext-dev-e2e -extension-developer-e2e: export INSTALL_DEFAULT_CATALOGS := false -extension-developer-e2e: run image-registry test-ext-dev-e2e kind-clean #EXHELP Run extension-developer e2e on local kind cluster +.PHONY: test-extension-developer-e2e +test-extension-developer-e2e: KIND_CLUSTER_NAME := operator-controller-ext-dev-e2e +test-extension-developer-e2e: export INSTALL_DEFAULT_CATALOGS := false +test-extension-developer-e2e: run image-registry extension-developer-e2e kind-clean #HELP Run extension-developer e2e on local kind cluster .PHONY: run-latest-release run-latest-release: - curl -L -s https://github.com/operator-framework/operator-controller/releases/latest/download/$(notdir $(RELEASE_INSTALL)) | bash -s + curl -L -s https://github.com/operator-framework/operator-controller/releases/latest/download/$(notdir $(STANDARD_RELEASE_INSTALL)) | bash -s .PHONY: pre-upgrade-setup pre-upgrade-setup: @@ -319,7 +317,7 @@ test-upgrade-e2e: kind-cluster run-latest-release image-registry pre-upgrade-set .PHONY: e2e-coverage e2e-coverage: - COVERAGE_OUTPUT=./coverage/e2e.out ./hack/test/e2e-coverage.sh + COVERAGE_NAME=$(COVERAGE_NAME) ./hack/test/e2e-coverage.sh #SECTION KIND Cluster Operations @@ -329,7 +327,7 @@ kind-load: $(KIND) #EXHELP Loads the currently constructed images into the KIND $(CONTAINER_RUNTIME) save $(CATD_IMG) | $(KIND) load image-archive /dev/stdin --name $(KIND_CLUSTER_NAME) .PHONY: kind-deploy -kind-deploy: export MANIFEST := $(RELEASE_MANIFEST) +kind-deploy: export MANIFEST := $(STANDARD_RELEASE_MANIFEST) kind-deploy: export DEFAULT_CATALOG := $(RELEASE_CATALOGS) kind-deploy: manifests @echo -e "\n\U1F4D8 Using $(SOURCE_MANIFEST) as source manifest\n" @@ -436,13 +434,16 @@ release: $(GORELEASER) #EXHELP Runs goreleaser for the operator-controller. By d OPCON_IMAGE_REPO=$(OPCON_IMAGE_REPO) CATD_IMAGE_REPO=$(CATD_IMAGE_REPO) $(GORELEASER) $(GORELEASER_ARGS) .PHONY: quickstart -quickstart: export MANIFEST := "https://github.com/operator-framework/operator-controller/releases/download/$(VERSION)/$(notdir $(RELEASE_MANIFEST))" +quickstart: export STANDARD_MANIFEST_URL := "https://github.com/operator-framework/operator-controller/releases/download/$(VERSION)/$(notdir $(STANDARD_RELEASE_MANIFEST))" +quickstart: export EXPERIMENTAL_MANIFEST_URL := "https://github.com/operator-framework/operator-controller/releases/download/$(VERSION)/$(notdir $(EXPERIMENTAL_RELEASE_MANIFEST))" quickstart: export DEFAULT_CATALOG := "https://github.com/operator-framework/operator-controller/releases/download/$(VERSION)/$(notdir $(RELEASE_CATALOGS))" quickstart: manifests #EXHELP Generate the unified installation release manifests and scripts. # Update the stored standard manifests for distribution - sed "s/:devel/:$(VERSION)/g" $(STANDARD_MANIFEST) | sed "s/cert-git-version/cert-$(VERSION)/g" > $(RELEASE_MANIFEST) + sed "s/:devel/:$(VERSION)/g" $(STANDARD_MANIFEST) | sed "s/cert-git-version/cert-$(VERSION)/g" > $(STANDARD_RELEASE_MANIFEST) + sed "s/:devel/:$(VERSION)/g" $(EXPERIMENTAL_MANIFEST) | sed "s/cert-git-version/cert-$(VERSION)/g" > $(EXPERIMENTAL_RELEASE_MANIFEST) cp $(CATALOGS_MANIFEST) $(RELEASE_CATALOGS) - envsubst '$$DEFAULT_CATALOG,$$CERT_MGR_VERSION,$$INSTALL_DEFAULT_CATALOGS,$$MANIFEST' < scripts/install.tpl.sh > $(RELEASE_INSTALL) + MANIFEST=$(STANDARD_MANIFEST_URL) envsubst '$$DEFAULT_CATALOG,$$CERT_MGR_VERSION,$$INSTALL_DEFAULT_CATALOGS,$$MANIFEST' < scripts/install.tpl.sh > $(STANDARD_RELEASE_INSTALL) + MANIFEST=$(EXPERIMENTAL_MANIFEST_URL) envsubst '$$DEFAULT_CATALOG,$$CERT_MGR_VERSION,$$INSTALL_DEFAULT_CATALOGS,$$MANIFEST' < scripts/install.tpl.sh > $(EXPERIMENTAL_RELEASE_INSTALL) ##@ Docs diff --git a/OWNERS b/OWNERS index 6dbe77690..b7e9325fe 100644 --- a/OWNERS +++ b/OWNERS @@ -1,5 +1,4 @@ approvers: - - operator-controller-approvers + - olmv1-approvers reviewers: - - operator-controller-approvers - - operator-controller-reviewers + - olmv1-reviewers diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES index 52dba52e0..d24c20b01 100644 --- a/OWNERS_ALIASES +++ b/OWNERS_ALIASES @@ -1,25 +1,49 @@ - aliases: - # contributors who can approve any PRs in the repo - operator-controller-approvers: - - camilamacedo86 - - grokspawn + olmv1-approvers: - joelanford - kevinrizza - perdasilva - - thetechnick - tmshort - # contributors who can review/lgtm any PRs in the repo - operator-controller-reviewers: + olmv1-reviewers: - anik120 - ankitathomas - bentito + - camilamacedo86 - dtfranz - - gallettilance - - gavinmbell - - LalatenduMohanty + - grokspawn + - joelanford - oceanc80 - OchiengEd + - perdasilva - rashmigottipati + - thetechnick + - tmshort - trgeiger + + api-approvers: + - grokspawn + - thetechnick + + catalogd-approvers: + - grokspawn + + operator-controller-approvers: + - thetechnick + + cmd-approvers: + - grokspawn + + manifest-approvers: + - camilamacedo86 + + ci-approvers: + - camilamacedo86 + + docs-approvers: + - michaelryanpeter + + docs-draft-approvers: + - camilamacedo86 + - grokspawn + - thetechnick diff --git a/api/OWNERS b/api/OWNERS new file mode 100644 index 000000000..71df7cfc5 --- /dev/null +++ b/api/OWNERS @@ -0,0 +1,2 @@ +approvers: + - api-approvers diff --git a/cmd/OWNERS b/cmd/OWNERS new file mode 100644 index 000000000..740420d64 --- /dev/null +++ b/cmd/OWNERS @@ -0,0 +1,2 @@ +approvers: + - cmd-approvers diff --git a/codecov.yml b/codecov.yml index 11acffacb..bbe044b0f 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,6 +1,8 @@ codecov: notify: - after_n_builds: 3 + # Configure the 4 builds to wait before sending a notification. + # test-unit, test-regression, test-e2e and test-experimental-e2e. + after_n_builds: 4 # Configure the paths to include in coverage reports. # Exclude documentation, YAML configurations, and test files. diff --git a/commitchecker.yaml b/commitchecker.yaml index 58f2f2b5c..c6d5b4d5d 100644 --- a/commitchecker.yaml +++ b/commitchecker.yaml @@ -1,4 +1,4 @@ -expectedMergeBase: 8cf5bdaf21ac3a211654c60ebb8bf1d31109a94b +expectedMergeBase: 3d6a33b60dab6aedec2b676eba3a7631d3961340 upstreamBranch: main upstreamOrg: operator-framework upstreamRepo: operator-controller diff --git a/config/OWNERS b/config/OWNERS new file mode 100644 index 000000000..b44dad0ea --- /dev/null +++ b/config/OWNERS @@ -0,0 +1,2 @@ +approvers: + - manifest-approvers diff --git a/config/base/catalogd/crd/OWNERS b/config/base/catalogd/crd/OWNERS new file mode 100644 index 000000000..71df7cfc5 --- /dev/null +++ b/config/base/catalogd/crd/OWNERS @@ -0,0 +1,2 @@ +approvers: + - api-approvers diff --git a/config/base/operator-controller/crd/OWNERS b/config/base/operator-controller/crd/OWNERS new file mode 100644 index 000000000..71df7cfc5 --- /dev/null +++ b/config/base/operator-controller/crd/OWNERS @@ -0,0 +1,2 @@ +approvers: + - api-approvers diff --git a/config/components/cert-manager/ca/issuers.yaml b/config/components/cert-manager/ca/issuers.yaml index 00e149d56..7725ebff0 100644 --- a/config/components/cert-manager/ca/issuers.yaml +++ b/config/components/cert-manager/ca/issuers.yaml @@ -19,6 +19,7 @@ spec: annotations: cert-manager.io/allow-direct-injection: "true" privateKey: + rotationPolicy: Always algorithm: ECDSA size: 256 issuerRef: diff --git a/config/components/cert-manager/catalogd/resources/certificate.yaml b/config/components/cert-manager/catalogd/resources/certificate.yaml index 63375760c..561dbe44e 100644 --- a/config/components/cert-manager/catalogd/resources/certificate.yaml +++ b/config/components/cert-manager/catalogd/resources/certificate.yaml @@ -10,6 +10,7 @@ spec: - catalogd-service.olmv1-system.svc - catalogd-service.olmv1-system.svc.cluster.local privateKey: + rotationPolicy: Always algorithm: ECDSA size: 256 issuerRef: diff --git a/config/components/cert-manager/operator-controller/resources/manager_cert.yaml b/config/components/cert-manager/operator-controller/resources/manager_cert.yaml index c001d946a..cbea2243e 100644 --- a/config/components/cert-manager/operator-controller/resources/manager_cert.yaml +++ b/config/components/cert-manager/operator-controller/resources/manager_cert.yaml @@ -9,6 +9,7 @@ spec: - operator-controller-service.olmv1-system.svc - operator-controller-service.olmv1-system.svc.cluster.local privateKey: + rotationPolicy: Always algorithm: ECDSA size: 256 issuerRef: diff --git a/config/overlays/prometheus/prometheus_rule.yaml b/config/overlays/prometheus/prometheus_rule.yaml index 16e4bfd1a..5bd7e120b 100644 --- a/config/overlays/prometheus/prometheus_rule.yaml +++ b/config/overlays/prometheus/prometheus_rule.yaml @@ -22,13 +22,13 @@ spec: annotations: description: "container {{ $labels.container }} of pod {{ $labels.pod }} experienced OOM event(s); count={{ $value }}" - alert: operator-controller-memory-growth - expr: deriv(sum(container_memory_working_set_bytes{pod=~"operator-controller.*",container="manager"})[5m:]) > 50_000 + expr: deriv(sum(container_memory_working_set_bytes{pod=~"operator-controller.*",container="manager"})[5m:]) > 100_000 for: 5m keep_firing_for: 1d annotations: description: "operator-controller pod memory usage growing at a high rate for 5 minutes: {{ $value | humanize }}B/sec" - alert: catalogd-memory-growth - expr: deriv(sum(container_memory_working_set_bytes{pod=~"catalogd.*",container="manager"})[5m:]) > 50_000 + expr: deriv(sum(container_memory_working_set_bytes{pod=~"catalogd.*",container="manager"})[5m:]) > 100_000 for: 5m keep_firing_for: 1d annotations: diff --git a/config/overlays/tilt-local-dev/patches/catalogd.yaml b/config/overlays/tilt-local-dev/patches/catalogd.yaml index b273a0c9b..4df906921 100644 --- a/config/overlays/tilt-local-dev/patches/catalogd.yaml +++ b/config/overlays/tilt-local-dev/patches/catalogd.yaml @@ -7,4 +7,4 @@ value: null - op: remove # remove --leader-elect so container doesn't restart during breakpoints - path: /spec/template/spec/containers/0/args/2 + path: /spec/template/spec/containers/0/args/0 diff --git a/docs/OWNERS b/docs/OWNERS index d1a8d41f1..342c5f631 100644 --- a/docs/OWNERS +++ b/docs/OWNERS @@ -1,23 +1,2 @@ approvers: - # contributors who can approve any docs PRs in the repo - - michaelryanpeter -reviewers: - # contributors who can review/lgtm any docs PRs in the repo - - anik120 - - ankitathomas - - bentito - - camilamacedo86 - - dtfranz - - gallettilance - - gavinmbell - - grokspawn - - joelanford - - kevinrizza - - LalatenduMohanty - - oceanc80 - - OchiengEd - - perdasilva - - rashmigottipati - - thetechnick - - tmshort - - trgeiger + - docs-approvers diff --git a/docs/draft/OWNERS b/docs/draft/OWNERS new file mode 100644 index 000000000..c81ed4110 --- /dev/null +++ b/docs/draft/OWNERS @@ -0,0 +1,2 @@ +approvers: + - docs-draft-approvers diff --git a/go.mod b/go.mod index 0c327499f..18ab3c00d 100644 --- a/go.mod +++ b/go.mod @@ -1,17 +1,17 @@ module github.com/operator-framework/operator-controller -go 1.24.3 +go 1.24.4 require ( github.com/BurntSushi/toml v1.5.0 github.com/Masterminds/semver/v3 v3.4.0 github.com/blang/semver/v4 v4.0.0 github.com/cert-manager/cert-manager v1.18.2 - github.com/containerd/containerd v1.7.27 - github.com/containers/image/v5 v5.36.0 + github.com/containerd/containerd v1.7.28 + github.com/containers/image/v5 v5.36.1 github.com/fsnotify/fsnotify v1.9.0 github.com/go-logr/logr v1.4.3 - github.com/golang-jwt/jwt/v5 v5.2.3 + github.com/golang-jwt/jwt/v5 v5.3.0 github.com/google/go-cmp v0.7.0 github.com/google/go-containerregistry v0.20.6 github.com/google/renameio/v2 v2.0.0 @@ -19,16 +19,17 @@ require ( github.com/klauspost/compress v1.18.0 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.1 - github.com/operator-framework/api v0.32.0 + github.com/operator-framework/api v0.33.0 github.com/operator-framework/helm-operator-plugins v0.8.0 github.com/operator-framework/operator-registry v1.56.0 - github.com/prometheus/client_golang v1.22.0 + github.com/prometheus/client_golang v1.23.0 + github.com/prometheus/common v0.65.0 github.com/spf13/cobra v1.9.1 github.com/stretchr/testify v1.10.0 golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b - golang.org/x/mod v0.26.0 + golang.org/x/mod v0.27.0 golang.org/x/sync v0.16.0 - golang.org/x/tools v0.35.0 + golang.org/x/tools v0.36.0 gopkg.in/yaml.v2 v2.4.0 helm.sh/helm/v3 v3.18.4 k8s.io/api v0.33.2 @@ -44,7 +45,7 @@ require ( sigs.k8s.io/controller-runtime v0.21.0 sigs.k8s.io/controller-tools v0.18.0 sigs.k8s.io/crdify v0.4.1-0.20250613143457-398e4483fb58 - sigs.k8s.io/yaml v1.5.0 + sigs.k8s.io/yaml v1.6.0 ) require ( @@ -84,14 +85,14 @@ require ( github.com/containers/common v0.63.1 // indirect github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect github.com/containers/ocicrypt v1.2.1 // indirect - github.com/containers/storage v1.59.0 // indirect + github.com/containers/storage v1.59.1 // indirect github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467 // indirect github.com/cyphar/filepath-securejoin v0.4.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/cli v28.3.2+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect - github.com/docker/docker v28.3.2+incompatible // indirect + github.com/docker/docker v28.3.3+incompatible // indirect github.com/docker/docker-credential-helpers v0.9.3 // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect @@ -118,7 +119,7 @@ require ( github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/btree v1.1.3 // indirect - github.com/google/cel-go v0.25.0 // indirect + github.com/google/cel-go v0.26.0 // indirect github.com/google/gnostic-models v0.6.9 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.6.0 // indirect @@ -177,7 +178,6 @@ require ( github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/proglottis/gpgme v0.1.4 // indirect github.com/prometheus/client_model v0.6.2 // indirect - github.com/prometheus/common v0.65.0 // indirect github.com/prometheus/procfs v0.16.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/rubenv/sql-migrate v1.8.0 // indirect @@ -216,12 +216,12 @@ require ( go.opentelemetry.io/proto/otlp v1.7.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.3 // indirect - golang.org/x/crypto v0.40.0 // indirect - golang.org/x/net v0.42.0 // indirect + golang.org/x/crypto v0.41.0 // indirect + golang.org/x/net v0.43.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sys v0.34.0 // indirect - golang.org/x/term v0.33.0 // indirect - golang.org/x/text v0.27.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/term v0.34.0 // indirect + golang.org/x/text v0.28.0 // indirect golang.org/x/time v0.12.0 // indirect golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index f20214b30..fef7d9773 100644 --- a/go.sum +++ b/go.sum @@ -57,8 +57,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo= github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins= -github.com/containerd/containerd v1.7.27 h1:yFyEyojddO3MIGVER2xJLWoCIn+Up4GaHFquP7hsFII= -github.com/containerd/containerd v1.7.27/go.mod h1:xZmPnl75Vc+BLGt4MIfu6bp+fy03gdHAn9bz+FreFR0= +github.com/containerd/containerd v1.7.28 h1:Nsgm1AtcmEh4AHAJ4gGlNSaKgXiNccU270Dnf81FQ3c= +github.com/containerd/containerd v1.7.28/go.mod h1:azUkWcOvHrWvaiUjSQH0fjzuHIwSPg1WL5PshGP4Szs= github.com/containerd/containerd/api v1.9.0 h1:HZ/licowTRazus+wt9fM6r/9BQO7S0vD5lMcWspGIg0= github.com/containerd/containerd/api v1.9.0/go.mod h1:GhghKFmTR3hNtyznBoQ0EMWr9ju5AqHjcZPsSpTKutI= github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4= @@ -79,14 +79,14 @@ github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++ github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk= github.com/containers/common v0.63.1 h1:6g02gbW34PaRVH4Heb2Pk11x0SdbQ+8AfeKKeQGqYBE= github.com/containers/common v0.63.1/go.mod h1:+3GCotSqNdIqM3sPs152VvW7m5+Mg8Kk+PExT3G9hZw= -github.com/containers/image/v5 v5.36.0 h1:Zh+xFcLjRmicnOT5AFPHH/xj+e3s9ojDN/9X2Kx1+Jo= -github.com/containers/image/v5 v5.36.0/go.mod h1:VZ6cyDHbxZoOt4dklUJ+WNEH9FrgSgfH3qUBYKFlcT0= +github.com/containers/image/v5 v5.36.1 h1:6zpXBqR59UcAzoKpa/By5XekeqFV+htWYfr65+Cgjqo= +github.com/containers/image/v5 v5.36.1/go.mod h1:b4GMKH2z/5t6/09utbse2ZiLK/c72GuGLFdp7K69eA4= github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA= github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY= github.com/containers/ocicrypt v1.2.1 h1:0qIOTT9DoYwcKmxSt8QJt+VzMY18onl9jUXsxpVhSmM= github.com/containers/ocicrypt v1.2.1/go.mod h1:aD0AAqfMp0MtwqWgHM1bUwe1anx0VazI108CRrSKINQ= -github.com/containers/storage v1.59.0 h1:r2pYSTzQpJTROZbjJQ54Z0GT+rUC6+wHzlSY8yPjsXk= -github.com/containers/storage v1.59.0/go.mod h1:KoAYHnAjP3/cTsRS+mmWZGkufSY2GACiKQ4V3ZLQnR0= +github.com/containers/storage v1.59.1 h1:11Zu68MXsEQGBBd+GadPrHPpWeqjKS8hJDGiAHgIqDs= +github.com/containers/storage v1.59.1/go.mod h1:KoAYHnAjP3/cTsRS+mmWZGkufSY2GACiKQ4V3ZLQnR0= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= @@ -112,8 +112,8 @@ github.com/docker/cli v28.3.2+incompatible h1:mOt9fcLE7zaACbxW1GeS65RI67wIJrTnqS github.com/docker/cli v28.3.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v28.3.2+incompatible h1:wn66NJ6pWB1vBZIilP8G3qQPqHy5XymfYn5vsqeA5oA= -github.com/docker/docker v28.3.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI= +github.com/docker/docker v28.3.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8= github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= @@ -186,8 +186,8 @@ github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v5 v5.2.3 h1:kkGXqQOBSDDWRhWNXTFpqGSCMyh/PLnqUvMGJPDJDs0= -github.com/golang-jwt/jwt/v5 v5.2.3/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= +github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang-migrate/migrate/v4 v4.18.3 h1:EYGkoOsvgHHfm5U/naS1RP/6PL/Xv3S4B/swMiAmDLs= github.com/golang-migrate/migrate/v4 v4.18.3/go.mod h1:99BKpIi6ruaaXRM1A77eqZ+FWPQ3cfRa+ZVy5bmWMaY= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -210,8 +210,8 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/cel-go v0.25.0 h1:jsFw9Fhn+3y2kBbltZR4VEz5xKkcIFRPDnuEzAGv5GY= -github.com/google/cel-go v0.25.0/go.mod h1:hjEb6r5SuOSlhCHmFoLzu8HGCERvIsDAbxDAyNU/MmI= +github.com/google/cel-go v0.26.0 h1:DPGjXackMpJWH680oGY4lZhYjIameYmR+/6RBdDGmaI= +github.com/google/cel-go v0.26.0/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM= github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw= github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -279,6 +279,8 @@ github.com/joelanford/ignore v0.1.1 h1:vKky5RDoPT+WbONrbQBgOn95VV/UPh4ejlyAbbzgn github.com/joelanford/ignore v0.1.1/go.mod h1:8eho/D8fwQ3rIXrLwE23AaeaGDNXqLE9QJ3zJ4LIPCw= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -352,6 +354,8 @@ github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/ github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= @@ -368,8 +372,8 @@ github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJw github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww= github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/operator-framework/api v0.32.0 h1:LZSZr7at3NrjsjwQVNsYD+04o5wMq75jrR0dMYiIIH8= -github.com/operator-framework/api v0.32.0/go.mod h1:OGJo6HUYxoQwpGaLr0lPJzSek51RiXajJSSa8Jzjvp8= +github.com/operator-framework/api v0.33.0 h1:Tdu9doXz6Key2riIiP3/JPahHEgFBXAqyWQN4kOITS8= +github.com/operator-framework/api v0.33.0/go.mod h1:sEh1VqwQCJUj+l/rKNWPDEJdFNAbdTu8QcM+x+wdYYo= github.com/operator-framework/helm-operator-plugins v0.8.0 h1:0f6HOQC5likkf0b/OvGvw7nhDb6h8Cj5twdCNjwNzMc= github.com/operator-framework/helm-operator-plugins v0.8.0/go.mod h1:Sc+8bE38xTCgCChBUvtq/PxatEg9fAypr7S5iAw8nlA= github.com/operator-framework/operator-lib v0.17.0 h1:cbz51wZ9+GpWR1ZYP4CSKSSBxDlWxmmnseaHVZZjZt4= @@ -393,8 +397,8 @@ github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= github.com/proglottis/gpgme v0.1.4 h1:3nE7YNA70o2aLjcg63tXMOhPD7bplfE5CBdV+hLAm2M= github.com/proglottis/gpgme v0.1.4/go.mod h1:5LoXMgpE4bttgwwdv9bLs/vwqv3qV7F4glEEZ7mRKrM= -github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= -github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= +github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc= +github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= @@ -559,8 +563,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= -golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= -golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= +golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= +golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o= golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8= @@ -574,8 +578,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= -golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= +golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -592,8 +596,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= -golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= @@ -628,8 +632,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= -golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -639,8 +643,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= -golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg= -golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0= +golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= +golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= @@ -650,8 +654,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= -golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= -golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -666,8 +670,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= -golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= +golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= golang.org/x/tools/go/expect v0.1.0-deprecated h1:jY2C5HGYR5lqex3gEniOQL0r7Dq5+VGVgY1nudX5lXY= golang.org/x/tools/go/expect v0.1.0-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= @@ -781,5 +785,5 @@ sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxO sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI= sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= -sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ= -sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4= +sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= +sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/hack/OWNERS b/hack/OWNERS new file mode 100644 index 000000000..835cabe50 --- /dev/null +++ b/hack/OWNERS @@ -0,0 +1,2 @@ +approvers: + - ci-approvers diff --git a/hack/test/e2e-coverage.sh b/hack/test/e2e-coverage.sh index 05aee8703..49c8db3d7 100755 --- a/hack/test/e2e-coverage.sh +++ b/hack/test/e2e-coverage.sh @@ -2,7 +2,7 @@ set -euo pipefail -COVERAGE_OUTPUT="${COVERAGE_OUTPUT:-${ROOT_DIR}/coverage/e2e.out}" +COVERAGE_NAME="${COVERAGE_NAME:-e2e}" OPERATOR_CONTROLLER_NAMESPACE="olmv1-system" OPERATOR_CONTROLLER_MANAGER_DEPLOYMENT_NAME="operator-controller-controller-manager" @@ -13,7 +13,8 @@ CATALOGD_MANAGER_DEPLOYMENT_NAME="catalogd-controller-manager" COPY_POD_NAME="e2e-coverage-copy-pod" # Create a temporary directory for coverage -COVERAGE_DIR=${ROOT_DIR}/coverage/e2e +COVERAGE_OUTPUT=${ROOT_DIR}/coverage/${COVERAGE_NAME}.out +COVERAGE_DIR=${ROOT_DIR}/coverage/${COVERAGE_NAME} rm -rf ${COVERAGE_DIR} && mkdir -p ${COVERAGE_DIR} # Coverage-instrumented binary produces coverage on termination, diff --git a/internal/catalogd/OWNERS b/internal/catalogd/OWNERS new file mode 100644 index 000000000..84b5bd1cc --- /dev/null +++ b/internal/catalogd/OWNERS @@ -0,0 +1,2 @@ +approvers: + - catalogd-approvers diff --git a/internal/operator-controller/OWNERS b/internal/operator-controller/OWNERS new file mode 100644 index 000000000..3174715ba --- /dev/null +++ b/internal/operator-controller/OWNERS @@ -0,0 +1,2 @@ +approvers: + - operator-controller-approvers diff --git a/manifests/OWNERS b/manifests/OWNERS new file mode 100644 index 000000000..b44dad0ea --- /dev/null +++ b/manifests/OWNERS @@ -0,0 +1,2 @@ +approvers: + - manifest-approvers diff --git a/manifests/experimental-e2e.yaml b/manifests/experimental-e2e.yaml index d3adf46e5..a91833bd7 100644 --- a/manifests/experimental-e2e.yaml +++ b/manifests/experimental-e2e.yaml @@ -1863,6 +1863,7 @@ spec: name: self-sign-issuer privateKey: algorithm: ECDSA + rotationPolicy: Always size: 256 secretName: olmv1-ca secretTemplate: @@ -1887,6 +1888,7 @@ spec: name: olmv1-ca privateKey: algorithm: ECDSA + rotationPolicy: Always size: 256 secretName: catalogd-service-cert-git-version --- @@ -1907,6 +1909,7 @@ spec: name: olmv1-ca privateKey: algorithm: ECDSA + rotationPolicy: Always size: 256 secretName: olmv1-cert --- diff --git a/manifests/experimental.yaml b/manifests/experimental.yaml index 7b0d2b9a3..00dc14153 100644 --- a/manifests/experimental.yaml +++ b/manifests/experimental.yaml @@ -1816,6 +1816,7 @@ spec: name: self-sign-issuer privateKey: algorithm: ECDSA + rotationPolicy: Always size: 256 secretName: olmv1-ca secretTemplate: @@ -1840,6 +1841,7 @@ spec: name: olmv1-ca privateKey: algorithm: ECDSA + rotationPolicy: Always size: 256 secretName: catalogd-service-cert-git-version --- @@ -1860,6 +1862,7 @@ spec: name: olmv1-ca privateKey: algorithm: ECDSA + rotationPolicy: Always size: 256 secretName: olmv1-cert --- diff --git a/manifests/standard-e2e.yaml b/manifests/standard-e2e.yaml index a8aff9838..1f46a03d4 100644 --- a/manifests/standard-e2e.yaml +++ b/manifests/standard-e2e.yaml @@ -1858,6 +1858,7 @@ spec: name: self-sign-issuer privateKey: algorithm: ECDSA + rotationPolicy: Always size: 256 secretName: olmv1-ca secretTemplate: @@ -1882,6 +1883,7 @@ spec: name: olmv1-ca privateKey: algorithm: ECDSA + rotationPolicy: Always size: 256 secretName: catalogd-service-cert-git-version --- @@ -1902,6 +1904,7 @@ spec: name: olmv1-ca privateKey: algorithm: ECDSA + rotationPolicy: Always size: 256 secretName: olmv1-cert --- diff --git a/manifests/standard.yaml b/manifests/standard.yaml index fa2546305..b4c70c252 100644 --- a/manifests/standard.yaml +++ b/manifests/standard.yaml @@ -1811,6 +1811,7 @@ spec: name: self-sign-issuer privateKey: algorithm: ECDSA + rotationPolicy: Always size: 256 secretName: olmv1-ca secretTemplate: @@ -1835,6 +1836,7 @@ spec: name: olmv1-ca privateKey: algorithm: ECDSA + rotationPolicy: Always size: 256 secretName: catalogd-service-cert-git-version --- @@ -1855,6 +1857,7 @@ spec: name: olmv1-ca privateKey: algorithm: ECDSA + rotationPolicy: Always size: 256 secretName: olmv1-cert --- diff --git a/requirements.txt b/requirements.txt index 8f4dc9633..327eebf35 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ Babel==2.17.0 beautifulsoup4==4.13.4 -certifi==2025.7.14 +certifi==2025.8.3 charset-normalizer==3.4.2 click==8.1.8 colorama==0.4.6 @@ -10,24 +10,24 @@ idna==3.10 Jinja2==3.1.6 lxml==6.0.0 Markdown==3.8.2 -markdown2==2.5.3 +markdown2==2.5.4 MarkupSafe==3.0.2 mergedeep==1.3.4 mkdocs==1.6.1 -mkdocs-material==9.6.15 +mkdocs-material==9.6.16 mkdocs-material-extensions==1.3.1 packaging==25.0 paginate==0.5.7 pathspec==0.12.1 platformdirs==4.3.8 Pygments==2.19.2 -pymdown-extensions==10.16 +pymdown-extensions==10.16.1 pyquery==2.0.1 python-dateutil==2.9.0.post0 PyYAML==6.0.2 pyyaml_env_tag==1.1 readtime==3.0.0 -regex==2024.11.6 +regex==2025.7.34 requests==2.32.4 six==1.17.0 soupsieve==2.7 diff --git a/scripts/OWNERS b/scripts/OWNERS new file mode 100644 index 000000000..b44dad0ea --- /dev/null +++ b/scripts/OWNERS @@ -0,0 +1,2 @@ +approvers: + - manifest-approvers diff --git a/test/convert/README.md b/test/convert/README.md deleted file mode 100644 index 590c65730..000000000 --- a/test/convert/README.md +++ /dev/null @@ -1,7 +0,0 @@ -## registry+v1 bundle generation regression tests - -This directory includes test cases for the rukpak/convert package based on real bundle data. -The manifests are generated and manually/visually verified for correctness. - -The `generate-manifests.go` tool is used to generate the tests cases by calling convert.Convert on bundles -in the `testdata` directory. diff --git a/test/e2e/cluster_extension_install_test.go b/test/e2e/cluster_extension_install_test.go index 5ce97b4ee..3c9dcbc2a 100644 --- a/test/e2e/cluster_extension_install_test.go +++ b/test/e2e/cluster_extension_install_test.go @@ -10,6 +10,7 @@ import ( "github.com/google/go-containerregistry/pkg/crane" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" networkingv1 "k8s.io/api/networking/v1" rbacv1 "k8s.io/api/rbac/v1" @@ -20,6 +21,7 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/rand" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" ocv1 "github.com/operator-framework/operator-controller/api/v1" @@ -204,20 +206,32 @@ func createClusterRoleAndBindingForSA(ctx context.Context, name string, sa *core } func testInit(t *testing.T) (*ocv1.ClusterExtension, *ocv1.ClusterCatalog, *corev1.ServiceAccount, *corev1.Namespace) { - var err error - - clusterExtensionName := fmt.Sprintf("clusterextension-%s", rand.String(8)) + ce, cc := testInitClusterExtensionClusterCatalog(t) + sa, ns := testInitServiceAccountNamespace(t, ce.Name) + return ce, cc, sa, ns +} - ns, err := createNamespace(context.Background(), clusterExtensionName) - require.NoError(t, err) +func testInitClusterExtensionClusterCatalog(t *testing.T) (*ocv1.ClusterExtension, *ocv1.ClusterCatalog) { + ceName := fmt.Sprintf("clusterextension-%s", rand.String(8)) - clusterExtension := &ocv1.ClusterExtension{ + ce := &ocv1.ClusterExtension{ ObjectMeta: metav1.ObjectMeta{ - Name: clusterExtensionName, + Name: ceName, }, } - extensionCatalog, err := createTestCatalog(context.Background(), testCatalogName, os.Getenv(testCatalogRefEnvVar)) + cc, err := createTestCatalog(context.Background(), testCatalogName, os.Getenv(testCatalogRefEnvVar)) + require.NoError(t, err) + + validateCatalogUnpack(t) + + return ce, cc +} + +func testInitServiceAccountNamespace(t *testing.T, clusterExtensionName string) (*corev1.ServiceAccount, *corev1.Namespace) { + var err error + + ns, err := createNamespace(context.Background(), clusterExtensionName) require.NoError(t, err) name := types.NamespacedName{ @@ -228,9 +242,7 @@ func testInit(t *testing.T) (*ocv1.ClusterExtension, *ocv1.ClusterCatalog, *core sa, err := createServiceAccount(context.Background(), name, clusterExtensionName) require.NoError(t, err) - validateCatalogUnpack(t) - - return clusterExtension, extensionCatalog, sa, ns + return sa, ns } func validateCatalogUnpack(t *testing.T) { @@ -292,35 +304,42 @@ func ensureNoExtensionResources(t *testing.T, clusterExtensionName string) { } func testCleanup(t *testing.T, cat *ocv1.ClusterCatalog, clusterExtension *ocv1.ClusterExtension, sa *corev1.ServiceAccount, ns *corev1.Namespace) { - t.Logf("By deleting ClusterCatalog %q", cat.Name) - require.NoError(t, c.Delete(context.Background(), cat)) - require.Eventually(t, func() bool { - err := c.Get(context.Background(), types.NamespacedName{Name: cat.Name}, &ocv1.ClusterCatalog{}) - return errors.IsNotFound(err) - }, pollDuration, pollInterval) - - t.Logf("By deleting ClusterExtension %q", clusterExtension.Name) - require.NoError(t, c.Delete(context.Background(), clusterExtension)) - require.Eventually(t, func() bool { - err := c.Get(context.Background(), types.NamespacedName{Name: clusterExtension.Name}, &ocv1.ClusterExtension{}) - return errors.IsNotFound(err) - }, pollDuration, pollInterval) + if cat != nil { + t.Logf("By deleting ClusterCatalog %q", cat.Name) + require.NoError(t, c.Delete(context.Background(), cat)) + require.Eventually(t, func() bool { + err := c.Get(context.Background(), types.NamespacedName{Name: cat.Name}, &ocv1.ClusterCatalog{}) + return errors.IsNotFound(err) + }, pollDuration, pollInterval) + } - t.Logf("By deleting ServiceAccount %q", sa.Name) - require.NoError(t, c.Delete(context.Background(), sa)) - require.Eventually(t, func() bool { - err := c.Get(context.Background(), types.NamespacedName{Name: sa.Name, Namespace: sa.Namespace}, &corev1.ServiceAccount{}) - return errors.IsNotFound(err) - }, pollDuration, pollInterval) + if clusterExtension != nil { + t.Logf("By deleting ClusterExtension %q", clusterExtension.Name) + require.NoError(t, c.Delete(context.Background(), clusterExtension)) + require.Eventually(t, func() bool { + err := c.Get(context.Background(), types.NamespacedName{Name: clusterExtension.Name}, &ocv1.ClusterExtension{}) + return errors.IsNotFound(err) + }, pollDuration, pollInterval) + ensureNoExtensionResources(t, clusterExtension.Name) + } - ensureNoExtensionResources(t, clusterExtension.Name) + if sa != nil { + t.Logf("By deleting ServiceAccount %q", sa.Name) + require.NoError(t, c.Delete(context.Background(), sa)) + require.Eventually(t, func() bool { + err := c.Get(context.Background(), types.NamespacedName{Name: sa.Name, Namespace: sa.Namespace}, &corev1.ServiceAccount{}) + return errors.IsNotFound(err) + }, pollDuration, pollInterval) + } - t.Logf("By deleting Namespace %q", ns.Name) - require.NoError(t, c.Delete(context.Background(), ns)) - require.Eventually(t, func() bool { - err := c.Get(context.Background(), types.NamespacedName{Name: ns.Name}, &corev1.Namespace{}) - return errors.IsNotFound(err) - }, pollDuration, pollInterval) + if ns != nil { + t.Logf("By deleting Namespace %q", ns.Name) + require.NoError(t, c.Delete(context.Background(), ns)) + require.Eventually(t, func() bool { + err := c.Get(context.Background(), types.NamespacedName{Name: ns.Name}, &corev1.Namespace{}) + return errors.IsNotFound(err) + }, pollDuration, pollInterval) + } } func TestClusterExtensionInstallRegistry(t *testing.T) { @@ -730,7 +749,7 @@ func TestClusterExtensionInstallReResolvesWhenCatalogIsPatched(t *testing.T) { // patch imageRef tag on test-catalog image with v2 image t.Log("By patching the catalog ImageRef to point to the v2 catalog") - updatedCatalogImage := fmt.Sprintf("%s/e2e/test-catalog:v2", os.Getenv("LOCAL_REGISTRY_HOST")) + updatedCatalogImage := fmt.Sprintf("%s/e2e/test-catalog:v2", os.Getenv("CLUSTER_REGISTRY_HOST")) err := patchTestCatalog(context.Background(), testCatalogName, updatedCatalogImage) require.NoError(t, err) require.EventuallyWithT(t, func(ct *assert.CollectT) { @@ -759,12 +778,12 @@ func TestClusterExtensionInstallReResolvesWhenNewCatalog(t *testing.T) { // Tag the image with the new tag var err error - v1Image := fmt.Sprintf("%s/%s", os.Getenv("CLUSTER_REGISTRY_HOST"), os.Getenv("E2E_TEST_CATALOG_V1")) + v1Image := fmt.Sprintf("%s/%s", os.Getenv("LOCAL_REGISTRY_HOST"), os.Getenv("E2E_TEST_CATALOG_V1")) err = crane.Tag(v1Image, latestImageTag, crane.Insecure) require.NoError(t, err) // create a test-catalog with latest image tag - latestCatalogImage := fmt.Sprintf("%s/e2e/test-catalog:latest", os.Getenv("LOCAL_REGISTRY_HOST")) + latestCatalogImage := fmt.Sprintf("%s/e2e/test-catalog:latest", os.Getenv("CLUSTER_REGISTRY_HOST")) extensionCatalog, err := createTestCatalog(context.Background(), testCatalogName, latestCatalogImage) require.NoError(t, err) clusterExtensionName := fmt.Sprintf("clusterextension-%s", rand.String(8)) @@ -810,7 +829,7 @@ func TestClusterExtensionInstallReResolvesWhenNewCatalog(t *testing.T) { // update tag on test-catalog image with v2 image t.Log("By updating the catalog tag to point to the v2 catalog") - v2Image := fmt.Sprintf("%s/%s", os.Getenv("CLUSTER_REGISTRY_HOST"), os.Getenv("E2E_TEST_CATALOG_V2")) + v2Image := fmt.Sprintf("%s/%s", os.Getenv("LOCAL_REGISTRY_HOST"), os.Getenv("E2E_TEST_CATALOG_V2")) err = crane.Tag(v2Image, latestImageTag, crane.Insecure) require.NoError(t, err) require.EventuallyWithT(t, func(ct *assert.CollectT) { @@ -882,22 +901,14 @@ func TestClusterExtensionInstallReResolvesWhenManagedContentChanged(t *testing.T }, pollDuration, pollInterval) } -func TestClusterExtensionRecoversFromInitialInstallFailedWhenFailureFixed(t *testing.T) { +func TestClusterExtensionRecoversFromNoNamespaceWhenFailureFixed(t *testing.T) { t.Log("When a cluster extension is installed from a catalog") t.Log("When the extension bundle format is registry+v1") - clusterExtension, extensionCatalog, _, ns := testInit(t) + t.Log("By not creating the Namespace and ServiceAccount") + clusterExtension, extensionCatalog := testInitClusterExtensionClusterCatalog(t) - name := rand.String(10) - sa := &corev1.ServiceAccount{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns.Name, - }, - } - err := c.Create(context.Background(), sa) - require.NoError(t, err) - defer testCleanup(t, extensionCatalog, clusterExtension, sa, ns) + defer testCleanup(t, extensionCatalog, clusterExtension, nil, nil) defer utils.CollectTestArtifacts(t, artifactName, c, cfg) clusterExtension.Spec = ocv1.ClusterExtensionSpec{ @@ -910,20 +921,136 @@ func TestClusterExtensionRecoversFromInitialInstallFailedWhenFailureFixed(t *tes }, }, }, - Namespace: ns.Name, + Namespace: clusterExtension.Name, ServiceAccount: ocv1.ServiceAccountReference{ - Name: sa.Name, + Name: clusterExtension.Name, }, } + t.Log("It resolves the specified package with correct bundle path") t.Log("By creating the ClusterExtension resource") require.NoError(t, c.Create(context.Background(), clusterExtension)) - t.Log("By eventually reporting a successful resolution and bundle path") + t.Log("By eventually reporting Progressing == True with Reason Retrying") + require.EventuallyWithT(t, func(ct *assert.CollectT) { + require.NoError(ct, c.Get(context.Background(), types.NamespacedName{Name: clusterExtension.Name}, clusterExtension)) + cond := apimeta.FindStatusCondition(clusterExtension.Status.Conditions, ocv1.TypeProgressing) + require.NotNil(ct, cond) + require.Equal(ct, metav1.ConditionTrue, cond.Status) + require.Equal(ct, ocv1.ReasonRetrying, cond.Reason) + }, pollDuration, pollInterval) + + t.Log("By eventually failing to install the package successfully due to no namespace") require.EventuallyWithT(t, func(ct *assert.CollectT) { require.NoError(ct, c.Get(context.Background(), types.NamespacedName{Name: clusterExtension.Name}, clusterExtension)) + cond := apimeta.FindStatusCondition(clusterExtension.Status.Conditions, ocv1.TypeInstalled) + require.NotNil(ct, cond) + require.Equal(ct, metav1.ConditionUnknown, cond.Status) + require.Equal(ct, ocv1.ReasonFailed, cond.Reason) + require.Contains(ct, cond.Message, fmt.Sprintf("service account %q not found in namespace %q: unable to authenticate with the Kubernetes cluster.", clusterExtension.Name, clusterExtension.Name)) }, pollDuration, pollInterval) + t.Log("By creating the Namespace and ServiceAccount") + sa, ns := testInitServiceAccountNamespace(t, clusterExtension.Name) + defer testCleanup(t, nil, nil, sa, ns) + + // NOTE: In order to ensure predictable results we need to ensure we have a single + // known failure with a singular fix operation. Additionally, due to the exponential + // backoff of this eventually check we MUST ensure we do not touch the ClusterExtension + // after creating int the Namespace and ServiceAccount. + t.Log("By eventually installing the package successfully") + require.EventuallyWithT(t, func(ct *assert.CollectT) { + require.NoError(ct, c.Get(context.Background(), types.NamespacedName{Name: clusterExtension.Name}, clusterExtension)) + cond := apimeta.FindStatusCondition(clusterExtension.Status.Conditions, ocv1.TypeInstalled) + require.NotNil(ct, cond) + require.Equal(ct, metav1.ConditionTrue, cond.Status) + require.Equal(ct, ocv1.ReasonSucceeded, cond.Reason) + require.Contains(ct, cond.Message, "Installed bundle") + require.NotEmpty(ct, clusterExtension.Status.Install) + }, pollDuration, pollInterval) + + t.Log("By eventually reporting Progressing == True with Reason Success") + require.EventuallyWithT(t, func(ct *assert.CollectT) { + require.NoError(ct, c.Get(context.Background(), types.NamespacedName{Name: clusterExtension.Name}, clusterExtension)) + cond := apimeta.FindStatusCondition(clusterExtension.Status.Conditions, ocv1.TypeProgressing) + require.NotNil(ct, cond) + require.Equal(ct, metav1.ConditionTrue, cond.Status) + require.Equal(ct, ocv1.ReasonSucceeded, cond.Reason) + }, pollDuration, pollInterval) +} + +func TestClusterExtensionRecoversFromExistingDeploymentWhenFailureFixed(t *testing.T) { + t.Log("When a cluster extension is installed from a catalog") + t.Log("When the extension bundle format is registry+v1") + + clusterExtension, extensionCatalog, sa, ns := testInit(t) + + defer testCleanup(t, extensionCatalog, clusterExtension, sa, ns) + defer utils.CollectTestArtifacts(t, artifactName, c, cfg) + + clusterExtension.Spec = ocv1.ClusterExtensionSpec{ + Source: ocv1.SourceConfig{ + SourceType: "Catalog", + Catalog: &ocv1.CatalogFilter{ + PackageName: "test", + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"olm.operatorframework.io/metadata.name": extensionCatalog.Name}, + }, + }, + }, + Namespace: clusterExtension.Name, + ServiceAccount: ocv1.ServiceAccountReference{ + Name: clusterExtension.Name, + }, + } + + t.Log("By creating a new Deployment that can not be adopted") + newDeployment := &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-operator", + Namespace: clusterExtension.Name, + }, + Spec: appsv1.DeploymentSpec{ + Replicas: ptr.To(int32(1)), + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"app": "test-operator"}, + }, + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{"app": "test-operator"}, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Command: []string{"sleep", "1000"}, + Image: "busybox", + ImagePullPolicy: corev1.PullAlways, + Name: "busybox", + SecurityContext: &corev1.SecurityContext{ + RunAsNonRoot: ptr.To(true), + RunAsUser: ptr.To(int64(1000)), + AllowPrivilegeEscalation: ptr.To(false), + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{ + "ALL", + }, + }, + SeccompProfile: &corev1.SeccompProfile{ + Type: corev1.SeccompProfileTypeRuntimeDefault, + }, + }, + }, + }, + }, + }, + }, + } + require.NoError(t, c.Create(context.Background(), newDeployment)) + + t.Log("It resolves the specified package with correct bundle path") + t.Log("By creating the ClusterExtension resource") + require.NoError(t, c.Create(context.Background(), clusterExtension)) + t.Log("By eventually reporting Progressing == True with Reason Retrying") require.EventuallyWithT(t, func(ct *assert.CollectT) { require.NoError(ct, c.Get(context.Background(), types.NamespacedName{Name: clusterExtension.Name}, clusterExtension)) @@ -933,23 +1060,23 @@ func TestClusterExtensionRecoversFromInitialInstallFailedWhenFailureFixed(t *tes require.Equal(ct, ocv1.ReasonRetrying, cond.Reason) }, pollDuration, pollInterval) - t.Log("By eventually failing to install the package successfully due to insufficient ServiceAccount permissions") + t.Log("By eventually failing to install the package successfully due to no adoption support") require.EventuallyWithT(t, func(ct *assert.CollectT) { require.NoError(ct, c.Get(context.Background(), types.NamespacedName{Name: clusterExtension.Name}, clusterExtension)) cond := apimeta.FindStatusCondition(clusterExtension.Status.Conditions, ocv1.TypeInstalled) require.NotNil(ct, cond) require.Equal(ct, metav1.ConditionFalse, cond.Status) require.Equal(ct, ocv1.ReasonFailed, cond.Reason) - require.Equal(ct, "No bundle installed", cond.Message) + require.Contains(ct, cond.Message, "No bundle installed") }, pollDuration, pollInterval) - t.Log("By fixing the ServiceAccount permissions") - require.NoError(t, createClusterRoleAndBindingForSA(context.Background(), name, sa, clusterExtension.Name)) + t.Log("By deleting the new Deployment") + require.NoError(t, c.Delete(context.Background(), newDeployment)) // NOTE: In order to ensure predictable results we need to ensure we have a single // known failure with a singular fix operation. Additionally, due to the exponential // backoff of this eventually check we MUST ensure we do not touch the ClusterExtension - // after creating and binding the needed permissions to the ServiceAccount. + // after deleting the Deployment. t.Log("By eventually installing the package successfully") require.EventuallyWithT(t, func(ct *assert.CollectT) { require.NoError(ct, c.Get(context.Background(), types.NamespacedName{Name: clusterExtension.Name}, clusterExtension)) diff --git a/test/e2e/e2e_suite_test.go b/test/e2e/e2e_suite_test.go index 354ef75f4..cf4f474eb 100644 --- a/test/e2e/e2e_suite_test.go +++ b/test/e2e/e2e_suite_test.go @@ -2,6 +2,7 @@ package e2e import ( "context" + "fmt" "os" "testing" @@ -15,6 +16,7 @@ import ( ocv1 "github.com/operator-framework/operator-controller/api/v1" "github.com/operator-framework/operator-controller/internal/operator-controller/scheme" + utils "github.com/operator-framework/operator-controller/test/utils" ) var ( @@ -23,9 +25,10 @@ var ( ) const ( - testCatalogRefEnvVar = "CATALOG_IMG" - testCatalogName = "test-catalog" - latestImageTag = "latest" + testSummaryOutputEnvVar = "GITHUB_STEP_SUMMARY" + testCatalogRefEnvVar = "CATALOG_IMG" + testCatalogName = "test-catalog" + latestImageTag = "latest" ) func TestMain(m *testing.M) { @@ -36,7 +39,12 @@ func TestMain(m *testing.M) { c, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) utilruntime.Must(err) - os.Exit(m.Run()) + res := m.Run() + err = utils.PrintSummary(testSummaryOutputEnvVar) + if err != nil { + fmt.Println("PrintSummary error", err) + } + os.Exit(res) } // createTestCatalog will create a new catalog on the test cluster, provided diff --git a/test/e2e/metrics_test.go b/test/e2e/metrics_test.go index 4a88c3dca..85908f4d5 100644 --- a/test/e2e/metrics_test.go +++ b/test/e2e/metrics_test.go @@ -129,7 +129,7 @@ func (c *MetricsTestConfig) getServiceAccountToken(t *testing.T) string { func (c *MetricsTestConfig) createCurlMetricsPod(t *testing.T) { t.Logf("Creating curl pod (%s/%s) to validate the metrics endpoint", c.namespace, c.curlPodName) cmd := exec.Command(c.client, "run", c.curlPodName, - "--image=curlimages/curl", + "--image=curlimages/curl:8.15.0", "--namespace", c.namespace, "--restart=Never", "--overrides", `{ @@ -137,7 +137,7 @@ func (c *MetricsTestConfig) createCurlMetricsPod(t *testing.T) { "terminationGradePeriodSeconds": 0, "containers": [{ "name": "curl", - "image": "curlimages/curl", + "image": "curlimages/curl:8.15.0", "command": ["sh", "-c", "sleep 3600"], "securityContext": { "allowPrivilegeEscalation": false, diff --git a/test/experimental-e2e/experimental_e2e_test.go b/test/experimental-e2e/experimental_e2e_test.go index 619cfd91e..8ead64e45 100644 --- a/test/experimental-e2e/experimental_e2e_test.go +++ b/test/experimental-e2e/experimental_e2e_test.go @@ -119,7 +119,7 @@ func TestWebhookSupport(t *testing.T) { Source: ocv1.CatalogSource{ Type: ocv1.SourceTypeImage, Image: &ocv1.ImageSource{ - Ref: fmt.Sprintf("%s/e2e/test-catalog:v1", os.Getenv("LOCAL_REGISTRY_HOST")), + Ref: fmt.Sprintf("%s/e2e/test-catalog:v1", os.Getenv("CLUSTER_REGISTRY_HOST")), PollIntervalMinutes: ptr.To(1), }, }, diff --git a/test/extension-developer-e2e/extension_developer_test.go b/test/extension-developer-e2e/extension_developer_test.go index ad7afdbac..a71f1f83d 100644 --- a/test/extension-developer-e2e/extension_developer_test.go +++ b/test/extension-developer-e2e/extension_developer_test.go @@ -32,6 +32,9 @@ func TestExtensionDeveloper(t *testing.T) { require.NoError(t, corev1.AddToScheme(scheme)) require.NoError(t, rbacv1.AddToScheme(scheme)) + require.NotEmpty(t, os.Getenv("CATALOG_IMG"), "environment variable CATALOG_IMG must be set") + require.NotEmpty(t, os.Getenv("REG_PKG_NAME"), "environment variable REG_PKG_NAME must be set") + c, err := client.New(cfg, client.Options{Scheme: scheme}) require.NoError(t, err) diff --git a/test/extension-developer-e2e/setup.sh b/test/extension-developer-e2e/setup.sh index 889080ad6..293341b33 100755 --- a/test/extension-developer-e2e/setup.sh +++ b/test/extension-developer-e2e/setup.sh @@ -11,27 +11,26 @@ following bundle formats: This script will ensure that all images built are loaded onto a KinD cluster with the name specified in the arguments. The following environment variables are required for configuring this script: -- \$CATALOG_IMG - the tag for the catalog image that contains the registry+v1 bundle. +- \$E2E_TEST_CATALOG_V1 - the tag for the catalog image that contains the registry+v1 bundle. - \$REG_PKG_NAME - the name of the package for the extension that uses the registry+v1 bundle format. -- \$LOCAL_REGISTRY_HOST - hostname:port of the local docker-registry setup.sh also takes 5 arguments. Usage: - setup.sh [OPERATOR_SDK] [CONTAINER_RUNTIME] [KUSTOMIZE] [KIND] [KIND_CLUSTER_NAME] [NAMESPACE] + setup.sh [OPERATOR_SDK] [CONTAINER_RUNTIME] [KUSTOMIZE] [LOCAL_REGISTRY_HOST] [CLUSTER_REGISTRY_HOST] " ######################################## # Input validation ######################################## -if [[ "$#" -ne 6 ]]; then +if [[ "$#" -ne 5 ]]; then echo "Illegal number of arguments passed" echo "${help}" exit 1 fi -if [[ -z "${CATALOG_IMG}" ]]; then - echo "\$CATALOG_IMG is required to be set" +if [[ -z "${E2E_TEST_CATALOG_V1}" ]]; then + echo "\$E2E_TEST_CATALOG_V1 is required to be set" echo "${help}" exit 1 fi @@ -42,12 +41,6 @@ if [[ -z "${REG_PKG_NAME}" ]]; then exit 1 fi -if [[ -z "${LOCAL_REGISTRY_HOST}" ]]; then - echo "\$LOCAL_REGISTRY_HOST is required to be set" - echo "${help}" - exit 1 -fi - ######################################## # Setup temp dir and local variables ######################################## @@ -64,15 +57,25 @@ mkdir -p "${REG_DIR}" operator_sdk=$1 container_tool=$2 kustomize=$3 -kind=$4 -kcluster_name=$5 -namespace=$6 +# The path we use to push the image from _outside_ the cluster +local_registry_host=$4 +# The path we use _inside_ the cluster +cluster_registry_host=$5 + +tls_flag="" +if [[ "$container_tool" == "podman" ]]; then + echo "Using podman container runtime; adding tls disable flag" + tls_flag="--tls-verify=false" +fi + +catalog_push_tag="${local_registry_host}/${E2E_TEST_CATALOG_V1}" +reg_pkg_name="${REG_PKG_NAME}" reg_img="${DOMAIN}/registry:v0.0.1" -reg_bundle_img="${LOCAL_REGISTRY_HOST}/bundles/registry-v1/registry-bundle:v0.0.1" +reg_bundle_path="bundles/registry-v1/registry-bundle:v0.0.1" -catalog_img="${CATALOG_IMG}" -reg_pkg_name="${REG_PKG_NAME}" +reg_bundle_img="${cluster_registry_host}/${reg_bundle_path}" +reg_bundle_push_tag="${local_registry_host}/${reg_bundle_path}" ######################################## # Create the registry+v1 based extension @@ -84,7 +87,7 @@ reg_pkg_name="${REG_PKG_NAME}" # NOTE: This is a rough edge that users will experience # The Makefile in the project scaffolded by operator-sdk uses an SDK binary -# in the path path if it is present. Override via `export` to ensure we use +# in the path if it is present. Override via `export` to ensure we use # the same version that we scaffolded with. # NOTE: this is a rough edge that users will experience @@ -102,7 +105,8 @@ reg_pkg_name="${REG_PKG_NAME}" make docker-build IMG="${reg_img}" && \ sed -i -e 's/$(OPERATOR_SDK) generate kustomize manifests -q/$(OPERATOR_SDK) generate kustomize manifests -q --interactive=false/g' Makefile && \ make bundle IMG="${reg_img}" VERSION=0.0.1 && \ - make bundle-build BUNDLE_IMG="${reg_bundle_img}" + make bundle-build BUNDLE_IMG="${reg_bundle_push_tag}" + ${container_tool} push ${reg_bundle_push_tag} ${tls_flag} ) ############################### @@ -149,107 +153,5 @@ cat < "${TMP_ROOT}"/catalog/index.yaml } EOF -# Add a .indexignore to make catalogd ignore -# reading the symlinked ..* files that are created when -# mounting a ConfigMap -cat < "${TMP_ROOT}"/catalog/.indexignore -..* -EOF - -kubectl create configmap -n "${namespace}" --from-file="${TMP_ROOT}"/catalog.Dockerfile extension-dev-e2e.dockerfile -kubectl create configmap -n "${namespace}" --from-file="${TMP_ROOT}"/catalog extension-dev-e2e.build-contents - -kubectl apply -f - << EOF -apiVersion: batch/v1 -kind: Job -metadata: - name: kaniko - namespace: "${namespace}" -spec: - template: - spec: - containers: - - name: kaniko - image: gcr.io/kaniko-project/executor:latest - args: ["--dockerfile=/workspace/catalog.Dockerfile", - "--context=/workspace/", - "--destination=${catalog_img}", - "--skip-tls-verify"] - volumeMounts: - - name: dockerfile - mountPath: /workspace/ - - name: build-contents - mountPath: /workspace/catalog/ - restartPolicy: Never - volumes: - - name: dockerfile - configMap: - name: extension-dev-e2e.dockerfile - items: - - key: catalog.Dockerfile - path: catalog.Dockerfile - - name: build-contents - configMap: - name: extension-dev-e2e.build-contents -EOF - -kubectl wait --for=condition=Complete -n "${namespace}" jobs/kaniko --timeout=60s - -# Make sure all files are removable. This is necessary because -# the Makefiles generated by the Operator-SDK have targets -# that install binaries under the bin/ directory. Those binaries -# don't have write permissions so they can't be removed unless -# we ensure they have the write permissions -chmod -R +w "${REG_DIR}/bin" - -# Load the bundle image into the docker-registry - -kubectl create configmap -n "${namespace}" --from-file="${REG_DIR}/bundle.Dockerfile" operator-controller-e2e-${reg_pkg_name}.root - -tgz="${REG_DIR}/manifests.tgz" -tar czf "${tgz}" -C "${REG_DIR}" bundle -kubectl create configmap -n "${namespace}" --from-file="${tgz}" operator-controller-${reg_pkg_name}.manifests - -kubectl apply -f - << EOF -apiVersion: batch/v1 -kind: Job -metadata: - name: "kaniko-${reg_pkg_name}" - namespace: "${namespace}" -spec: - template: - spec: - initContainers: - - name: copy-manifests - image: busybox - command: ['sh', '-c', 'cp /manifests-data/* /manifests'] - volumeMounts: - - name: manifests - mountPath: /manifests - - name: manifests-data - mountPath: /manifests-data - containers: - - name: kaniko - image: gcr.io/kaniko-project/executor:latest - args: ["--dockerfile=/workspace/bundle.Dockerfile", - "--context=tar:///workspace/manifests/manifests.tgz", - "--destination=${reg_bundle_img}", - "--skip-tls-verify"] - volumeMounts: - - name: dockerfile - mountPath: /workspace/ - - name: manifests - mountPath: /workspace/manifests/ - restartPolicy: Never - volumes: - - name: dockerfile - configMap: - name: operator-controller-e2e-${reg_pkg_name}.root - - name: manifests - emptyDir: {} - - name: manifests-data - configMap: - name: operator-controller-${reg_pkg_name}.manifests -EOF - -kubectl wait --for=condition=Complete -n "${namespace}" jobs/kaniko-${reg_pkg_name} --timeout=60s +${container_tool} build -f "${TMP_ROOT}/catalog.Dockerfile" -t "${catalog_push_tag}" "${TMP_ROOT}/" +${container_tool} push ${catalog_push_tag} ${tls_flag} diff --git a/test/regression/convert/convert_test.go b/test/regression/convert/convert_test.go new file mode 100644 index 000000000..1e70c08cf --- /dev/null +++ b/test/regression/convert/convert_test.go @@ -0,0 +1,120 @@ +/* +## registry+v1 bundle regression test + +This test in convert_test.go verifies that rendering registry+v1 bundles to manifests +always produces the same files and content. + +It runs: go run generate-manifests.go -output-dir=./testdata/tmp/rendered/ +Then compares: ./testdata/tmp/rendered/ vs ./testdata/expected-manifests/ + +Files are sorted by kind/namespace/name for consistency. + +To update expected output (only on purpose), run: + + go run generate-manifests.go -output-dir=./testdata/expected-manifests/ +*/ +package main + +import ( + "bytes" + "fmt" + "os" + "os/exec" + "path/filepath" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/require" +) + +// Test_RenderedOutputMatchesExpected runs generate-manifests.go, +// then compares the generated files in ./testdata/tmp/rendered/ +// against expected-manifests/. +// It fails if any file differs or is missing. +// TMP dir is cleaned up after test ends. +func Test_RenderedOutput_MatchesExpected(t *testing.T) { + tmpRoot := "./testdata/tmp/rendered/" + expectedRoot := "./testdata/expected-manifests/" + + // Remove the temporary output directory always + t.Cleanup(func() { + _ = os.RemoveAll("./testdata/tmp") + }) + + // Call the generate-manifests.go script to generate the manifests + // in the temporary directory. + cmd := exec.Command("go", "run", "generate-manifests.go", "-output-dir="+tmpRoot) + cmd.Stderr = os.Stderr + cmd.Stdout = os.Stdout + + err := cmd.Run() + require.NoError(t, err, "failed to generate manifests") + + // Compare structure + contents + err = compareDirs(expectedRoot, tmpRoot) + require.NoError(t, err, "rendered output differs from expected") +} + +// compareDirs compares expectedRootPath and generatedRootPath directories recursively. +// It returns an error if any file is missing, extra, or has content mismatch. +// On mismatch, it includes a detailed diff using cmp.Diff. +func compareDirs(expectedRootPath, generatedRootPath string) error { + // Step 1: Ensure every expected file exists in actual and contents match + err := filepath.Walk(expectedRootPath, func(expectedPath string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if info.IsDir() { + return nil + } + + relPath, err := filepath.Rel(expectedRootPath, expectedPath) + if err != nil { + return err + } + actualPath := filepath.Join(generatedRootPath, relPath) + + expectedBytes, err := os.ReadFile(expectedPath) + if err != nil { + return fmt.Errorf("failed to read expected file: %s", expectedPath) + } + actualBytes, err := os.ReadFile(actualPath) + if err != nil { + return fmt.Errorf("missing file: %s", relPath) + } + + if !bytes.Equal(expectedBytes, actualBytes) { + diff := cmp.Diff(string(expectedBytes), string(actualBytes)) + return fmt.Errorf("file content mismatch at: %s\nDiff (-expected +actual):\n%s", relPath, diff) + } + return nil + }) + if err != nil { + return err + } + + // Step 2: Ensure actual does not contain unexpected files + err = filepath.Walk(generatedRootPath, func(actualPath string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if info.IsDir() { + return nil + } + + relPath, err := filepath.Rel(generatedRootPath, actualPath) + if err != nil { + return err + } + expectedPath := filepath.Join(expectedRootPath, relPath) + + _, err = os.Stat(expectedPath) + if os.IsNotExist(err) { + return fmt.Errorf("unexpected extra file: %s", relPath) + } else if err != nil { + return fmt.Errorf("error checking expected file: %s", expectedPath) + } + return nil + }) + return err +} diff --git a/test/convert/generate-manifests.go b/test/regression/convert/generate-manifests.go similarity index 69% rename from test/convert/generate-manifests.go rename to test/regression/convert/generate-manifests.go index 147b05e36..b2a656550 100644 --- a/test/convert/generate-manifests.go +++ b/test/regression/convert/generate-manifests.go @@ -1,7 +1,20 @@ +// generate-manifests.go +// +// Renders registry+v1 bundles into YAML manifests for regression testing. +// Used by tests to make sure output from the BundleRenderer stays consistent. +// +// By default, writes to ./testdata/tmp/generate/. +// To update expected output, run: +// +// go run generate-manifests.go -output-dir=./testdata/expected-manifests/ +// +// Only re-generate if you intentionally change rendering behavior. +// Note that if the test fails is likely a regression in the renderer. package main import ( "cmp" + "flag" "fmt" "os" "path/filepath" @@ -16,11 +29,26 @@ import ( "github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/render/registryv1" ) +// This is a helper for a regression test to make sure the renderer output doesn't change. +// +// It renders known bundles into YAML files and writes them to a target output dir. +// By default, it writes to a temp path used in tests: +// +// ./testdata/tmp/rendered/ +// +// If you want to update the expected output, run it with: +// +// go run generate-manifests.go -output-dir=./testdata/expected-manifests/ +// +// Note: Expected output should never change unless the renderer changes which is unlikely. +// If the convert_test.go test fails, it likely means a regression was introduced in the renderer. func main() { bundleRootDir := "testdata/bundles/" - outputRootDir := "test/convert/expected-manifests/" + defaultOutputDir := "./testdata/tmp/rendered/" + outputRootDir := flag.String("output-dir", defaultOutputDir, "path to write rendered manifests to") + flag.Parse() - if err := os.RemoveAll(outputRootDir); err != nil { + if err := os.RemoveAll(*outputRootDir); err != nil { fmt.Printf("error removing output directory: %v\n", err) os.Exit(1) } @@ -52,7 +80,7 @@ func main() { }, } { bundlePath := filepath.Join(bundleRootDir, tc.bundle) - generatedManifestPath := filepath.Join(outputRootDir, tc.bundle, tc.testCaseName) + generatedManifestPath := filepath.Join(*outputRootDir, tc.bundle, tc.testCaseName) if err := generateManifests(generatedManifestPath, bundlePath, tc.installNamespace, tc.watchNamespace); err != nil { fmt.Printf("Error generating manifests: %v", err) os.Exit(1) diff --git a/testdata/bundles/argocd-operator.v0.6.0/manifests/argocd-operator-controller-manager-metrics-service_v1_service.yaml b/test/regression/convert/testdata/bundles/argocd-operator.v0.6.0/manifests/argocd-operator-controller-manager-metrics-service_v1_service.yaml similarity index 100% rename from testdata/bundles/argocd-operator.v0.6.0/manifests/argocd-operator-controller-manager-metrics-service_v1_service.yaml rename to test/regression/convert/testdata/bundles/argocd-operator.v0.6.0/manifests/argocd-operator-controller-manager-metrics-service_v1_service.yaml diff --git a/testdata/bundles/argocd-operator.v0.6.0/manifests/argocd-operator-manager-config_v1_configmap.yaml b/test/regression/convert/testdata/bundles/argocd-operator.v0.6.0/manifests/argocd-operator-manager-config_v1_configmap.yaml similarity index 100% rename from testdata/bundles/argocd-operator.v0.6.0/manifests/argocd-operator-manager-config_v1_configmap.yaml rename to test/regression/convert/testdata/bundles/argocd-operator.v0.6.0/manifests/argocd-operator-manager-config_v1_configmap.yaml diff --git a/testdata/bundles/argocd-operator.v0.6.0/manifests/argocd-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml b/test/regression/convert/testdata/bundles/argocd-operator.v0.6.0/manifests/argocd-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml similarity index 100% rename from testdata/bundles/argocd-operator.v0.6.0/manifests/argocd-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml rename to test/regression/convert/testdata/bundles/argocd-operator.v0.6.0/manifests/argocd-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml diff --git a/testdata/bundles/argocd-operator.v0.6.0/manifests/argocd-operator.v0.6.0.clusterserviceversion.yaml b/test/regression/convert/testdata/bundles/argocd-operator.v0.6.0/manifests/argocd-operator.v0.6.0.clusterserviceversion.yaml similarity index 100% rename from testdata/bundles/argocd-operator.v0.6.0/manifests/argocd-operator.v0.6.0.clusterserviceversion.yaml rename to test/regression/convert/testdata/bundles/argocd-operator.v0.6.0/manifests/argocd-operator.v0.6.0.clusterserviceversion.yaml diff --git a/testdata/bundles/argocd-operator.v0.6.0/manifests/argoproj.io_applications.yaml b/test/regression/convert/testdata/bundles/argocd-operator.v0.6.0/manifests/argoproj.io_applications.yaml similarity index 100% rename from testdata/bundles/argocd-operator.v0.6.0/manifests/argoproj.io_applications.yaml rename to test/regression/convert/testdata/bundles/argocd-operator.v0.6.0/manifests/argoproj.io_applications.yaml diff --git a/testdata/bundles/argocd-operator.v0.6.0/manifests/argoproj.io_applicationsets.yaml b/test/regression/convert/testdata/bundles/argocd-operator.v0.6.0/manifests/argoproj.io_applicationsets.yaml similarity index 100% rename from testdata/bundles/argocd-operator.v0.6.0/manifests/argoproj.io_applicationsets.yaml rename to test/regression/convert/testdata/bundles/argocd-operator.v0.6.0/manifests/argoproj.io_applicationsets.yaml diff --git a/testdata/bundles/argocd-operator.v0.6.0/manifests/argoproj.io_appprojects.yaml b/test/regression/convert/testdata/bundles/argocd-operator.v0.6.0/manifests/argoproj.io_appprojects.yaml similarity index 100% rename from testdata/bundles/argocd-operator.v0.6.0/manifests/argoproj.io_appprojects.yaml rename to test/regression/convert/testdata/bundles/argocd-operator.v0.6.0/manifests/argoproj.io_appprojects.yaml diff --git a/testdata/bundles/argocd-operator.v0.6.0/manifests/argoproj.io_argocdexports.yaml b/test/regression/convert/testdata/bundles/argocd-operator.v0.6.0/manifests/argoproj.io_argocdexports.yaml similarity index 100% rename from testdata/bundles/argocd-operator.v0.6.0/manifests/argoproj.io_argocdexports.yaml rename to test/regression/convert/testdata/bundles/argocd-operator.v0.6.0/manifests/argoproj.io_argocdexports.yaml diff --git a/testdata/bundles/argocd-operator.v0.6.0/manifests/argoproj.io_argocds.yaml b/test/regression/convert/testdata/bundles/argocd-operator.v0.6.0/manifests/argoproj.io_argocds.yaml similarity index 100% rename from testdata/bundles/argocd-operator.v0.6.0/manifests/argoproj.io_argocds.yaml rename to test/regression/convert/testdata/bundles/argocd-operator.v0.6.0/manifests/argoproj.io_argocds.yaml diff --git a/testdata/bundles/argocd-operator.v0.6.0/metadata/annotations.yaml b/test/regression/convert/testdata/bundles/argocd-operator.v0.6.0/metadata/annotations.yaml similarity index 100% rename from testdata/bundles/argocd-operator.v0.6.0/metadata/annotations.yaml rename to test/regression/convert/testdata/bundles/argocd-operator.v0.6.0/metadata/annotations.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/00_clusterrole_argocd-operator-metrics-reader.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/00_clusterrole_argocd-operator-metrics-reader.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/00_clusterrole_argocd-operator-metrics-reader.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/00_clusterrole_argocd-operator-metrics-reader.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/01_clusterrole_argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/01_clusterrole_argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/01_clusterrole_argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/01_clusterrole_argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/02_clusterrole_argocd-operator.v0.-3gkm3u8zfarktdile5wekso69zs9bgzb988mhjm0y6p.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/02_clusterrole_argocd-operator.v0.-3gkm3u8zfarktdile5wekso69zs9bgzb988mhjm0y6p.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/02_clusterrole_argocd-operator.v0.-3gkm3u8zfarktdile5wekso69zs9bgzb988mhjm0y6p.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/02_clusterrole_argocd-operator.v0.-3gkm3u8zfarktdile5wekso69zs9bgzb988mhjm0y6p.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/03_clusterrolebinding_argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/03_clusterrolebinding_argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/03_clusterrolebinding_argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/03_clusterrolebinding_argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/04_clusterrolebinding_argocd-operator.v0.-3gkm3u8zfarktdile5wekso69zs9bgzb988mhjm0y6p.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/04_clusterrolebinding_argocd-operator.v0.-3gkm3u8zfarktdile5wekso69zs9bgzb988mhjm0y6p.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/04_clusterrolebinding_argocd-operator.v0.-3gkm3u8zfarktdile5wekso69zs9bgzb988mhjm0y6p.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/04_clusterrolebinding_argocd-operator.v0.-3gkm3u8zfarktdile5wekso69zs9bgzb988mhjm0y6p.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/05_configmap_argocd-operator-manager-config.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/05_configmap_argocd-operator-manager-config.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/05_configmap_argocd-operator-manager-config.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/05_configmap_argocd-operator-manager-config.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/06_customresourcedefinition_applications.argoproj.io.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/06_customresourcedefinition_applications.argoproj.io.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/06_customresourcedefinition_applications.argoproj.io.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/06_customresourcedefinition_applications.argoproj.io.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/07_customresourcedefinition_applicationsets.argoproj.io.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/07_customresourcedefinition_applicationsets.argoproj.io.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/07_customresourcedefinition_applicationsets.argoproj.io.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/07_customresourcedefinition_applicationsets.argoproj.io.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/08_customresourcedefinition_appprojects.argoproj.io.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/08_customresourcedefinition_appprojects.argoproj.io.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/08_customresourcedefinition_appprojects.argoproj.io.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/08_customresourcedefinition_appprojects.argoproj.io.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/09_customresourcedefinition_argocdexports.argoproj.io.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/09_customresourcedefinition_argocdexports.argoproj.io.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/09_customresourcedefinition_argocdexports.argoproj.io.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/09_customresourcedefinition_argocdexports.argoproj.io.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/10_customresourcedefinition_argocds.argoproj.io.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/10_customresourcedefinition_argocds.argoproj.io.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/10_customresourcedefinition_argocds.argoproj.io.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/10_customresourcedefinition_argocds.argoproj.io.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/11_deployment_argocd-operator-controller-manager.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/11_deployment_argocd-operator-controller-manager.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/11_deployment_argocd-operator-controller-manager.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/11_deployment_argocd-operator-controller-manager.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/12_service_argocd-operator-controller-manager-metrics-service.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/12_service_argocd-operator-controller-manager-metrics-service.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/12_service_argocd-operator-controller-manager-metrics-service.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/12_service_argocd-operator-controller-manager-metrics-service.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/13_serviceaccount_argocd-operator-controller-manager.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/13_serviceaccount_argocd-operator-controller-manager.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/all-namespaces/13_serviceaccount_argocd-operator-controller-manager.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/all-namespaces/13_serviceaccount_argocd-operator-controller-manager.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/00_clusterrole_argocd-operator-metrics-reader.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/00_clusterrole_argocd-operator-metrics-reader.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/00_clusterrole_argocd-operator-metrics-reader.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/00_clusterrole_argocd-operator-metrics-reader.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/01_clusterrole_argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/01_clusterrole_argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/01_clusterrole_argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/01_clusterrole_argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/02_clusterrolebinding_argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/02_clusterrolebinding_argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/02_clusterrolebinding_argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/02_clusterrolebinding_argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/03_configmap_argocd-operator-manager-config.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/03_configmap_argocd-operator-manager-config.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/03_configmap_argocd-operator-manager-config.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/03_configmap_argocd-operator-manager-config.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/04_customresourcedefinition_applications.argoproj.io.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/04_customresourcedefinition_applications.argoproj.io.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/04_customresourcedefinition_applications.argoproj.io.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/04_customresourcedefinition_applications.argoproj.io.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/05_customresourcedefinition_applicationsets.argoproj.io.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/05_customresourcedefinition_applicationsets.argoproj.io.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/05_customresourcedefinition_applicationsets.argoproj.io.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/05_customresourcedefinition_applicationsets.argoproj.io.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/06_customresourcedefinition_appprojects.argoproj.io.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/06_customresourcedefinition_appprojects.argoproj.io.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/06_customresourcedefinition_appprojects.argoproj.io.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/06_customresourcedefinition_appprojects.argoproj.io.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/07_customresourcedefinition_argocdexports.argoproj.io.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/07_customresourcedefinition_argocdexports.argoproj.io.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/07_customresourcedefinition_argocdexports.argoproj.io.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/07_customresourcedefinition_argocdexports.argoproj.io.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/08_customresourcedefinition_argocds.argoproj.io.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/08_customresourcedefinition_argocds.argoproj.io.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/08_customresourcedefinition_argocds.argoproj.io.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/08_customresourcedefinition_argocds.argoproj.io.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/09_deployment_argocd-operator-controller-manager.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/09_deployment_argocd-operator-controller-manager.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/09_deployment_argocd-operator-controller-manager.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/09_deployment_argocd-operator-controller-manager.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/10_role_argocd-operator.v0-22gmilmgp91wu25is5i2ec598hni8owq3l71bbkl7iz3.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/10_role_argocd-operator.v0-22gmilmgp91wu25is5i2ec598hni8owq3l71bbkl7iz3.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/10_role_argocd-operator.v0-22gmilmgp91wu25is5i2ec598hni8owq3l71bbkl7iz3.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/10_role_argocd-operator.v0-22gmilmgp91wu25is5i2ec598hni8owq3l71bbkl7iz3.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/11_rolebinding_argocd-operator.v0-22gmilmgp91wu25is5i2ec598hni8owq3l71bbkl7iz3.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/11_rolebinding_argocd-operator.v0-22gmilmgp91wu25is5i2ec598hni8owq3l71bbkl7iz3.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/11_rolebinding_argocd-operator.v0-22gmilmgp91wu25is5i2ec598hni8owq3l71bbkl7iz3.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/11_rolebinding_argocd-operator.v0-22gmilmgp91wu25is5i2ec598hni8owq3l71bbkl7iz3.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/12_service_argocd-operator-controller-manager-metrics-service.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/12_service_argocd-operator-controller-manager-metrics-service.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/12_service_argocd-operator-controller-manager-metrics-service.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/12_service_argocd-operator-controller-manager-metrics-service.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/13_serviceaccount_argocd-operator-controller-manager.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/13_serviceaccount_argocd-operator-controller-manager.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/own-namespace/13_serviceaccount_argocd-operator-controller-manager.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/own-namespace/13_serviceaccount_argocd-operator-controller-manager.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/00_clusterrole_argocd-operator-metrics-reader.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/00_clusterrole_argocd-operator-metrics-reader.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/00_clusterrole_argocd-operator-metrics-reader.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/00_clusterrole_argocd-operator-metrics-reader.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/01_clusterrole_argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/01_clusterrole_argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/01_clusterrole_argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/01_clusterrole_argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/02_clusterrolebinding_argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/02_clusterrolebinding_argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/02_clusterrolebinding_argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/02_clusterrolebinding_argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/03_configmap_argocd-operator-manager-config.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/03_configmap_argocd-operator-manager-config.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/03_configmap_argocd-operator-manager-config.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/03_configmap_argocd-operator-manager-config.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/04_customresourcedefinition_applications.argoproj.io.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/04_customresourcedefinition_applications.argoproj.io.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/04_customresourcedefinition_applications.argoproj.io.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/04_customresourcedefinition_applications.argoproj.io.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/05_customresourcedefinition_applicationsets.argoproj.io.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/05_customresourcedefinition_applicationsets.argoproj.io.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/05_customresourcedefinition_applicationsets.argoproj.io.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/05_customresourcedefinition_applicationsets.argoproj.io.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/06_customresourcedefinition_appprojects.argoproj.io.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/06_customresourcedefinition_appprojects.argoproj.io.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/06_customresourcedefinition_appprojects.argoproj.io.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/06_customresourcedefinition_appprojects.argoproj.io.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/07_customresourcedefinition_argocdexports.argoproj.io.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/07_customresourcedefinition_argocdexports.argoproj.io.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/07_customresourcedefinition_argocdexports.argoproj.io.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/07_customresourcedefinition_argocdexports.argoproj.io.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/08_customresourcedefinition_argocds.argoproj.io.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/08_customresourcedefinition_argocds.argoproj.io.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/08_customresourcedefinition_argocds.argoproj.io.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/08_customresourcedefinition_argocds.argoproj.io.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/09_deployment_argocd-operator-controller-manager.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/09_deployment_argocd-operator-controller-manager.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/09_deployment_argocd-operator-controller-manager.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/09_deployment_argocd-operator-controller-manager.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/10_role_argocd-operator.v0-22gmilmgp91wu25is5i2ec598hni8owq3l71bbkl7iz3.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/10_role_argocd-operator.v0-22gmilmgp91wu25is5i2ec598hni8owq3l71bbkl7iz3.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/10_role_argocd-operator.v0-22gmilmgp91wu25is5i2ec598hni8owq3l71bbkl7iz3.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/10_role_argocd-operator.v0-22gmilmgp91wu25is5i2ec598hni8owq3l71bbkl7iz3.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/11_rolebinding_argocd-operator.v0-22gmilmgp91wu25is5i2ec598hni8owq3l71bbkl7iz3.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/11_rolebinding_argocd-operator.v0-22gmilmgp91wu25is5i2ec598hni8owq3l71bbkl7iz3.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/11_rolebinding_argocd-operator.v0-22gmilmgp91wu25is5i2ec598hni8owq3l71bbkl7iz3.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/11_rolebinding_argocd-operator.v0-22gmilmgp91wu25is5i2ec598hni8owq3l71bbkl7iz3.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/12_service_argocd-operator-controller-manager-metrics-service.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/12_service_argocd-operator-controller-manager-metrics-service.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/12_service_argocd-operator-controller-manager-metrics-service.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/12_service_argocd-operator-controller-manager-metrics-service.yaml diff --git a/test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/13_serviceaccount_argocd-operator-controller-manager.yaml b/test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/13_serviceaccount_argocd-operator-controller-manager.yaml similarity index 100% rename from test/convert/expected-manifests/argocd-operator.v0.6.0/single-namespace/13_serviceaccount_argocd-operator-controller-manager.yaml rename to test/regression/convert/testdata/expected-manifests/argocd-operator.v0.6.0/single-namespace/13_serviceaccount_argocd-operator-controller-manager.yaml diff --git a/test/utils/summary.go b/test/utils/summary.go new file mode 100644 index 000000000..d91ae3239 --- /dev/null +++ b/test/utils/summary.go @@ -0,0 +1,199 @@ +package utils + +import ( + "context" + "fmt" + "math" + "os" + "path/filepath" + "strings" + "text/template" + "time" + + "github.com/prometheus/client_golang/api" + v1 "github.com/prometheus/client_golang/api/prometheus/v1" + "github.com/prometheus/common/model" +) + +var ( + summaryTemplate = "summary.md.tmpl" + alertsTemplate = "alert.md.tmpl" + chartTemplate = "mermaid_chart.md.tmpl" + defaultPromUrl = "http://localhost:30900" +) + +type summaryAlerts struct { + FiringAlerts []summaryAlert + PendingAlerts []summaryAlert +} + +type summaryAlert struct { + v1.Alert + Name string + Description string +} + +type xychart struct { + Title string + YMax float64 + YMin float64 + YLabel string + Data string +} + +type githubSummary struct { + client api.Client + Pods []string +} + +func NewSummary(c api.Client, pods ...string) githubSummary { + return githubSummary{ + client: c, + Pods: pods, + } +} + +// PerformanceQuery queries the prometheus server and generates a mermaid xychart with the data. +// title - Display name of the xychart +// pod - Pod name with which to filter results from prometheus +// query - Prometheus query +// yLabel - Label of the Y axis i.e. "KB/s", "MB", etc. +// scaler - Constant by which to scale the results. For instance, cpu usage is more human-readable +// as "mCPU" vs "CPU", so we scale the results by a factor of 1,000. +func (s githubSummary) PerformanceQuery(title, pod, query string, yLabel string, scaler float64) (string, error) { + v1api := v1.NewAPI(s.client) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + fullQuery := fmt.Sprintf(query, pod) + result, warnings, err := v1api.Query(ctx, fullQuery, time.Now()) + if err != nil { + return "", err + } else if len(warnings) > 0 { + fmt.Printf("warnings returned from performance query; query=%s, warnings=%v", fullQuery, warnings) + } else if result.Type() != model.ValMatrix { + return "", fmt.Errorf("incompatible result type; need: %s, got: %s", model.ValMatrix, result.Type().String()) + } + + matrix, ok := result.(model.Matrix) + if !ok { + return "", fmt.Errorf("typecast for metrics samples failed; aborting") + } else if len(matrix) > 1 { + return "", fmt.Errorf("expected 1 set of results; got: %d", len(matrix)) + } + chart := xychart{ + Title: title, + YLabel: yLabel, + YMax: math.SmallestNonzeroFloat64, + YMin: math.MaxFloat64, + } + formattedData := make([]string, 0) + // matrix does not allow [] access, so we just do one iteration for the single result + for _, metric := range matrix { + if len(metric.Values) < 1 { + return "", fmt.Errorf("expected at least one data point; got: %d", len(metric.Values)) + } + for _, sample := range metric.Values { + floatSample := float64(sample.Value) * scaler + formattedData = append(formattedData, fmt.Sprintf("%f", floatSample)) + if floatSample > chart.YMax { + chart.YMax = floatSample + } + if floatSample < chart.YMin { + chart.YMin = floatSample + } + } + } + // Add some padding + chart.YMax = (chart.YMax + (math.Abs(chart.YMax) * 0.05)) + chart.YMin = (chart.YMin - (math.Abs(chart.YMin) * 0.05)) + // Pretty print the values, ex: [1,2,3,4] + chart.Data = strings.ReplaceAll(fmt.Sprintf("%v", formattedData), " ", ",") + + return executeTemplate(chartTemplate, chart) +} + +// Alerts queries the prometheus server for alerts and generates markdown output for anything found. +// If no alerts are found, the alerts section will contain only "None." in the final output. +func (s githubSummary) Alerts() (string, error) { + v1api := v1.NewAPI(s.client) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + result, err := v1api.Alerts(ctx) + if err != nil { + return "", err + } + + firingAlerts := make([]summaryAlert, 0) + pendingAlerts := make([]summaryAlert, 0) + if len(result.Alerts) > 0 { + for _, a := range result.Alerts { + aConv := summaryAlert{ + Alert: a, + Name: string(a.Labels["alertname"]), + Description: string(a.Annotations["description"]), + } + switch a.State { + case v1.AlertStateFiring: + firingAlerts = append(firingAlerts, aConv) + case v1.AlertStatePending: + pendingAlerts = append(pendingAlerts, aConv) + // Ignore AlertStateInactive; the alerts endpoint doesn't return them + } + } + } else { + return "None.", nil + } + + return executeTemplate(alertsTemplate, summaryAlerts{ + FiringAlerts: firingAlerts, + PendingAlerts: pendingAlerts, + }) +} + +func executeTemplate(templateFile string, obj any) (string, error) { + wd, err := os.Getwd() + if err != nil { + return "", fmt.Errorf("failed to get working directory: %w", err) + } + tmpl, err := template.New(templateFile).ParseGlob(filepath.Join(wd, "../utils/templates", templateFile)) + if err != nil { + return "", err + } + buffer := new(strings.Builder) + err = tmpl.Execute(buffer, obj) + if err != nil { + return "", err + } + return buffer.String(), nil +} + +// PrintSummary executes the main summary template, generating the full test report. +// The markdown is template-driven; the summary methods are called from within the +// template. This allows us to add or change queries (hopefully) without needing to +// touch code. The summary will be output to a file supplied by the env target. +func PrintSummary(envTarget string) error { + client, err := api.NewClient(api.Config{ + Address: defaultPromUrl, + }) + if err != nil { + fmt.Printf("Error creating prometheus client: %v\n", err) + os.Exit(1) + } + + summary := NewSummary(client, "operator-controller", "catalogd") + summaryMarkdown, err := executeTemplate(summaryTemplate, summary) + if err != nil { + return err + } + if path := os.Getenv(envTarget); path != "" { + err = os.WriteFile(path, []byte(summaryMarkdown), 0o600) + if err != nil { + return err + } + fmt.Printf("Test summary output to %s successful\n", envTarget) + } else { + fmt.Printf("No summary output specified; skipping") + } + return nil +} diff --git a/test/utils/templates/alert.md.tmpl b/test/utils/templates/alert.md.tmpl new file mode 100644 index 000000000..39f3e4287 --- /dev/null +++ b/test/utils/templates/alert.md.tmpl @@ -0,0 +1,16 @@ +{{- /* -------------------- Alert Template --------------------- */ -}} +{{define "alert"}} +| {{ .Name }} | {{ .Description }} | +| -------- | ------- | +| ActiveAt | {{ .ActiveAt }} | +| State | {{ .State }} | +{{- end}} + +### Firing Alerts +{{ range .FiringAlerts }} +{{ template "alert" .}} +{{ end }} +### Pending Alerts +{{ range .PendingAlerts }} +{{ template "alert" .}} +{{ end }} diff --git a/test/utils/templates/mermaid_chart.md.tmpl b/test/utils/templates/mermaid_chart.md.tmpl new file mode 100644 index 000000000..0a8ed1135 --- /dev/null +++ b/test/utils/templates/mermaid_chart.md.tmpl @@ -0,0 +1,17 @@ +
+ +```mermaid +--- +config: + xyChart: + showDataLabel: true + xAxis: + showLabel: false +--- +xychart-beta +title "{{ .Title }}" +y-axis "{{ .YLabel }}" {{printf "%f" .YMin}} --> {{printf "%f" .YMax}} +x-axis "time (start of test to end)" +line {{.Data}} +``` +
diff --git a/test/utils/templates/summary.md.tmpl b/test/utils/templates/summary.md.tmpl new file mode 100644 index 000000000..c094d49f3 --- /dev/null +++ b/test/utils/templates/summary.md.tmpl @@ -0,0 +1,22 @@ + +{{- /* ------------ Performance Statistics Template ------------ */ -}} +{{define "performanceStatistics" -}} +{{ range $index, $pod := .Pods }} +### {{$pod}} +#### Memory Usage +{{$.PerformanceQuery "Memory Usage" $pod `container_memory_working_set_bytes{pod=~"%s.*",container="manager"}[5m]` "MB" .000001}} + +#### Memory Growth Rate +{{$.PerformanceQuery "Memory Growth Rate" $pod `deriv(sum(container_memory_working_set_bytes{pod=~"%s.*",container="manager"})[5m:])[5m:]` "KB/s" .001}} + +#### CPU Usage +{{$.PerformanceQuery "CPU Usage" $pod `rate(container_cpu_usage_seconds_total{pod=~"%s.*",container="manager"}[5m])[5m:]` "mCPU" 1000}} +{{end}} +{{- end}} + +{{- /* ----------------- E2E Summary Markdown ------------------ */ -}} +# E2E Summary +## Alerts +{{.Alerts}} +## Performance +{{ template "performanceStatistics" . -}} diff --git a/testdata/build-test-registry.sh b/testdata/build-test-registry.sh index 3d92a726f..e2dcc0914 100755 --- a/testdata/build-test-registry.sh +++ b/testdata/build-test-registry.sh @@ -45,6 +45,7 @@ spec: - ${name}-controller-manager-metrics-service.${namespace}.svc - ${name}-controller-manager-metrics-service.${namespace}.svc.cluster.local privateKey: + rotationPolicy: Always algorithm: ECDSA size: 256 issuerRef: diff --git a/testdata/images/bundles/test-operator/v1.0.0/manifests/testoperator.clusterserviceversion.yaml b/testdata/images/bundles/test-operator/v1.0.0/manifests/testoperator.clusterserviceversion.yaml index a566e3595..3520f53db 100644 --- a/testdata/images/bundles/test-operator/v1.0.0/manifests/testoperator.clusterserviceversion.yaml +++ b/testdata/images/bundles/test-operator/v1.0.0/manifests/testoperator.clusterserviceversion.yaml @@ -58,7 +58,7 @@ spec: terminationGracePeriodSeconds: 0 containers: - name: busybox - image: busybox + image: busybox:1.36 command: - 'sleep' - '1000' diff --git a/testdata/images/bundles/webhook-operator/v0.0.1/manifests/webhook-operator.clusterserviceversion.yaml b/testdata/images/bundles/webhook-operator/v0.0.1/manifests/webhook-operator.clusterserviceversion.yaml index 0b8976f92..26506bd53 100644 --- a/testdata/images/bundles/webhook-operator/v0.0.1/manifests/webhook-operator.clusterserviceversion.yaml +++ b/testdata/images/bundles/webhook-operator/v0.0.1/manifests/webhook-operator.clusterserviceversion.yaml @@ -107,9 +107,6 @@ spec: name: webhook-server protocol: TCP resources: - limits: - cpu: 100m - memory: 30Mi requests: cpu: 100m memory: 20Mi diff --git a/vendor/github.com/containerd/containerd/remotes/docker/auth/fetch.go b/vendor/github.com/containerd/containerd/remotes/docker/auth/fetch.go index 244e03509..c9c224b2a 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/auth/fetch.go +++ b/vendor/github.com/containerd/containerd/remotes/docker/auth/fetch.go @@ -86,11 +86,11 @@ type TokenOptions struct { // OAuthTokenResponse is response from fetching token with a OAuth POST request type OAuthTokenResponse struct { - AccessToken string `json:"access_token"` - RefreshToken string `json:"refresh_token"` - ExpiresIn int `json:"expires_in"` - IssuedAt time.Time `json:"issued_at"` - Scope string `json:"scope"` + AccessToken string `json:"access_token"` + RefreshToken string `json:"refresh_token"` + ExpiresInSeconds int `json:"expires_in"` + IssuedAt time.Time `json:"issued_at"` + Scope string `json:"scope"` } // FetchTokenWithOAuth fetches a token using a POST request @@ -152,11 +152,11 @@ func FetchTokenWithOAuth(ctx context.Context, client *http.Client, headers http. // FetchTokenResponse is response from fetching token with GET request type FetchTokenResponse struct { - Token string `json:"token"` - AccessToken string `json:"access_token"` - ExpiresIn int `json:"expires_in"` - IssuedAt time.Time `json:"issued_at"` - RefreshToken string `json:"refresh_token"` + Token string `json:"token"` + AccessToken string `json:"access_token"` + ExpiresInSeconds int `json:"expires_in"` + IssuedAt time.Time `json:"issued_at"` + RefreshToken string `json:"refresh_token"` } // FetchToken fetches a token using a GET request diff --git a/vendor/github.com/containerd/containerd/remotes/docker/authorizer.go b/vendor/github.com/containerd/containerd/remotes/docker/authorizer.go index 2bf388e8c..6aabe95a4 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/authorizer.go +++ b/vendor/github.com/containerd/containerd/remotes/docker/authorizer.go @@ -24,6 +24,7 @@ import ( "net/http" "strings" "sync" + "time" "github.com/containerd/log" @@ -206,9 +207,10 @@ func (a *dockerAuthorizer) AddResponses(ctx context.Context, responses []*http.R // authResult is used to control limit rate. type authResult struct { sync.WaitGroup - token string - refreshToken string - err error + token string + refreshToken string + expirationTime *time.Time + err error } // authHandler is used to handle auth request per registry server. @@ -271,8 +273,12 @@ func (ah *authHandler) doBearerAuth(ctx context.Context) (token, refreshToken st // Docs: https://docs.docker.com/registry/spec/auth/scope scoped := strings.Join(to.Scopes, " ") + // Keep track of the expiration time of cached bearer tokens so they can be + // refreshed when they expire without a server roundtrip. + var expirationTime *time.Time + ah.Lock() - if r, exist := ah.scopedTokens[scoped]; exist { + if r, exist := ah.scopedTokens[scoped]; exist && (r.expirationTime == nil || r.expirationTime.After(time.Now())) { ah.Unlock() r.Wait() return r.token, r.refreshToken, r.err @@ -286,7 +292,7 @@ func (ah *authHandler) doBearerAuth(ctx context.Context) (token, refreshToken st defer func() { token = fmt.Sprintf("Bearer %s", token) - r.token, r.refreshToken, r.err = token, refreshToken, err + r.token, r.refreshToken, r.err, r.expirationTime = token, refreshToken, err, expirationTime r.Done() }() @@ -312,6 +318,7 @@ func (ah *authHandler) doBearerAuth(ctx context.Context) (token, refreshToken st if err != nil { return "", "", err } + expirationTime = getExpirationTime(resp.ExpiresInSeconds) return resp.Token, resp.RefreshToken, nil } log.G(ctx).WithFields(log.Fields{ @@ -321,6 +328,7 @@ func (ah *authHandler) doBearerAuth(ctx context.Context) (token, refreshToken st } return "", "", err } + expirationTime = getExpirationTime(resp.ExpiresInSeconds) return resp.AccessToken, resp.RefreshToken, nil } // do request anonymously @@ -328,9 +336,18 @@ func (ah *authHandler) doBearerAuth(ctx context.Context) (token, refreshToken st if err != nil { return "", "", fmt.Errorf("failed to fetch anonymous token: %w", err) } + expirationTime = getExpirationTime(resp.ExpiresInSeconds) return resp.Token, resp.RefreshToken, nil } +func getExpirationTime(expiresInSeconds int) *time.Time { + if expiresInSeconds <= 0 { + return nil + } + expirationTime := time.Now().Add(time.Duration(expiresInSeconds) * time.Second) + return &expirationTime +} + func invalidAuthorization(ctx context.Context, c auth.Challenge, responses []*http.Response) (retry bool, _ error) { errStr := c.Parameters["error"] if errStr == "" { diff --git a/vendor/github.com/containerd/containerd/version/version.go b/vendor/github.com/containerd/containerd/version/version.go index e806164ca..cd788cbde 100644 --- a/vendor/github.com/containerd/containerd/version/version.go +++ b/vendor/github.com/containerd/containerd/version/version.go @@ -23,7 +23,7 @@ var ( Package = "github.com/containerd/containerd" // Version holds the complete version number. Filled in at linking time. - Version = "1.7.27+unknown" + Version = "1.7.28+unknown" // Revision is filled with the VCS (e.g. git) revision being used to build // the program at linking time. diff --git a/vendor/github.com/containers/image/v5/version/version.go b/vendor/github.com/containers/image/v5/version/version.go index bfff8a345..5510e2e79 100644 --- a/vendor/github.com/containers/image/v5/version/version.go +++ b/vendor/github.com/containers/image/v5/version/version.go @@ -8,7 +8,7 @@ const ( // VersionMinor is for functionality in a backwards-compatible manner VersionMinor = 36 // VersionPatch is for backwards-compatible bug fixes - VersionPatch = 0 + VersionPatch = 1 // VersionDev indicates development branch. Releases will be empty string. VersionDev = "" diff --git a/vendor/github.com/containers/storage/pkg/archive/archive.go b/vendor/github.com/containers/storage/pkg/archive/archive.go index 0de672662..a66d2b891 100644 --- a/vendor/github.com/containers/storage/pkg/archive/archive.go +++ b/vendor/github.com/containers/storage/pkg/archive/archive.go @@ -697,7 +697,10 @@ func (ta *tarWriter) addFile(headers *addFileData) error { } if !headers.fi.IsDir() && hasHardlinks(headers.fi) { - ta.SeenFiles[getInodeFromStat(headers.fi.Sys())] = headers.hdr.Name + ino := getInodeFromStat(headers.fi.Sys()) + if _, seen := ta.SeenFiles[ino]; !seen { + ta.SeenFiles[ino] = headers.hdr.Name + } } return nil diff --git a/vendor/github.com/golang-jwt/jwt/v5/errors.go b/vendor/github.com/golang-jwt/jwt/v5/errors.go index 23bb616dd..14e007516 100644 --- a/vendor/github.com/golang-jwt/jwt/v5/errors.go +++ b/vendor/github.com/golang-jwt/jwt/v5/errors.go @@ -2,6 +2,7 @@ package jwt import ( "errors" + "fmt" "strings" ) @@ -47,3 +48,42 @@ func joinErrors(errs ...error) error { errs: errs, } } + +// Unwrap implements the multiple error unwrapping for this error type, which is +// possible in Go 1.20. +func (je joinedError) Unwrap() []error { + return je.errs +} + +// newError creates a new error message with a detailed error message. The +// message will be prefixed with the contents of the supplied error type. +// Additionally, more errors, that provide more context can be supplied which +// will be appended to the message. This makes use of Go 1.20's possibility to +// include more than one %w formatting directive in [fmt.Errorf]. +// +// For example, +// +// newError("no keyfunc was provided", ErrTokenUnverifiable) +// +// will produce the error string +// +// "token is unverifiable: no keyfunc was provided" +func newError(message string, err error, more ...error) error { + var format string + var args []any + if message != "" { + format = "%w: %s" + args = []any{err, message} + } else { + format = "%w" + args = []any{err} + } + + for _, e := range more { + format += ": %w" + args = append(args, e) + } + + err = fmt.Errorf(format, args...) + return err +} diff --git a/vendor/github.com/golang-jwt/jwt/v5/errors_go1_20.go b/vendor/github.com/golang-jwt/jwt/v5/errors_go1_20.go deleted file mode 100644 index a893d355e..000000000 --- a/vendor/github.com/golang-jwt/jwt/v5/errors_go1_20.go +++ /dev/null @@ -1,47 +0,0 @@ -//go:build go1.20 -// +build go1.20 - -package jwt - -import ( - "fmt" -) - -// Unwrap implements the multiple error unwrapping for this error type, which is -// possible in Go 1.20. -func (je joinedError) Unwrap() []error { - return je.errs -} - -// newError creates a new error message with a detailed error message. The -// message will be prefixed with the contents of the supplied error type. -// Additionally, more errors, that provide more context can be supplied which -// will be appended to the message. This makes use of Go 1.20's possibility to -// include more than one %w formatting directive in [fmt.Errorf]. -// -// For example, -// -// newError("no keyfunc was provided", ErrTokenUnverifiable) -// -// will produce the error string -// -// "token is unverifiable: no keyfunc was provided" -func newError(message string, err error, more ...error) error { - var format string - var args []any - if message != "" { - format = "%w: %s" - args = []any{err, message} - } else { - format = "%w" - args = []any{err} - } - - for _, e := range more { - format += ": %w" - args = append(args, e) - } - - err = fmt.Errorf(format, args...) - return err -} diff --git a/vendor/github.com/golang-jwt/jwt/v5/errors_go_other.go b/vendor/github.com/golang-jwt/jwt/v5/errors_go_other.go deleted file mode 100644 index 2ad542f00..000000000 --- a/vendor/github.com/golang-jwt/jwt/v5/errors_go_other.go +++ /dev/null @@ -1,78 +0,0 @@ -//go:build !go1.20 -// +build !go1.20 - -package jwt - -import ( - "errors" - "fmt" -) - -// Is implements checking for multiple errors using [errors.Is], since multiple -// error unwrapping is not possible in versions less than Go 1.20. -func (je joinedError) Is(err error) bool { - for _, e := range je.errs { - if errors.Is(e, err) { - return true - } - } - - return false -} - -// wrappedErrors is a workaround for wrapping multiple errors in environments -// where Go 1.20 is not available. It basically uses the already implemented -// functionality of joinedError to handle multiple errors with supplies a -// custom error message that is identical to the one we produce in Go 1.20 using -// multiple %w directives. -type wrappedErrors struct { - msg string - joinedError -} - -// Error returns the stored error string -func (we wrappedErrors) Error() string { - return we.msg -} - -// newError creates a new error message with a detailed error message. The -// message will be prefixed with the contents of the supplied error type. -// Additionally, more errors, that provide more context can be supplied which -// will be appended to the message. Since we cannot use of Go 1.20's possibility -// to include more than one %w formatting directive in [fmt.Errorf], we have to -// emulate that. -// -// For example, -// -// newError("no keyfunc was provided", ErrTokenUnverifiable) -// -// will produce the error string -// -// "token is unverifiable: no keyfunc was provided" -func newError(message string, err error, more ...error) error { - // We cannot wrap multiple errors here with %w, so we have to be a little - // bit creative. Basically, we are using %s instead of %w to produce the - // same error message and then throw the result into a custom error struct. - var format string - var args []any - if message != "" { - format = "%s: %s" - args = []any{err, message} - } else { - format = "%s" - args = []any{err} - } - errs := []error{err} - - for _, e := range more { - format += ": %s" - args = append(args, e) - errs = append(errs, e) - } - - err = &wrappedErrors{ - msg: fmt.Sprintf(format, args...), - joinedError: joinedError{errs: errs}, - } - return err -} diff --git a/vendor/github.com/golang-jwt/jwt/v5/rsa_pss.go b/vendor/github.com/golang-jwt/jwt/v5/rsa_pss.go index 7c216ae00..f17590cc4 100644 --- a/vendor/github.com/golang-jwt/jwt/v5/rsa_pss.go +++ b/vendor/github.com/golang-jwt/jwt/v5/rsa_pss.go @@ -1,6 +1,3 @@ -//go:build go1.4 -// +build go1.4 - package jwt import ( diff --git a/vendor/github.com/google/cel-go/cel/BUILD.bazel b/vendor/github.com/google/cel-go/cel/BUILD.bazel index 4a0425a8e..c12e4904d 100644 --- a/vendor/github.com/google/cel-go/cel/BUILD.bazel +++ b/vendor/github.com/google/cel-go/cel/BUILD.bazel @@ -11,8 +11,8 @@ go_library( "decls.go", "env.go", "folding.go", - "io.go", "inlining.go", + "io.go", "library.go", "macro.go", "optimizer.go", @@ -64,8 +64,8 @@ go_test( "decls_test.go", "env_test.go", "folding_test.go", - "io_test.go", "inlining_test.go", + "io_test.go", "optimizer_test.go", "prompt_test.go", "validator_test.go", @@ -90,8 +90,8 @@ go_test( "//test/proto2pb:go_default_library", "//test/proto3pb:go_default_library", "@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library", - "@org_golang_google_protobuf//proto:go_default_library", "@org_golang_google_protobuf//encoding/prototext:go_default_library", + "@org_golang_google_protobuf//proto:go_default_library", "@org_golang_google_protobuf//types/known/structpb:go_default_library", "@org_golang_google_protobuf//types/known/wrapperspb:go_default_library", ], diff --git a/vendor/github.com/google/cel-go/cel/folding.go b/vendor/github.com/google/cel-go/cel/folding.go index 0c7ecc616..40d843ece 100644 --- a/vendor/github.com/google/cel-go/cel/folding.go +++ b/vendor/github.com/google/cel-go/cel/folding.go @@ -38,6 +38,23 @@ func MaxConstantFoldIterations(limit int) ConstantFoldingOption { } } +// Adds an Activation which provides known values for the folding evaluator +// +// Any values the activation provides will be used by the constant folder and turned into +// literals in the AST. +// +// Defaults to the NoVars() Activation +func FoldKnownValues(knownValues Activation) ConstantFoldingOption { + return func(opt *constantFoldingOptimizer) (*constantFoldingOptimizer, error) { + if knownValues != nil { + opt.knownValues = knownValues + } else { + opt.knownValues = NoVars() + } + return opt, nil + } +} + // NewConstantFoldingOptimizer creates an optimizer which inlines constant scalar an aggregate // literal values within function calls and select statements with their evaluated result. func NewConstantFoldingOptimizer(opts ...ConstantFoldingOption) (ASTOptimizer, error) { @@ -56,6 +73,7 @@ func NewConstantFoldingOptimizer(opts ...ConstantFoldingOption) (ASTOptimizer, e type constantFoldingOptimizer struct { maxFoldIterations int + knownValues Activation } // Optimize queries the expression graph for scalar and aggregate literal expressions within call and @@ -68,7 +86,7 @@ func (opt *constantFoldingOptimizer) Optimize(ctx *OptimizerContext, a *ast.AST) // Walk the list of foldable expression and continue to fold until there are no more folds left. // All of the fold candidates returned by the constantExprMatcher should succeed unless there's // a logic bug with the selection of expressions. - constantExprMatcherCapture := func(e ast.NavigableExpr) bool { return constantExprMatcher(ctx, a, e) } + constantExprMatcherCapture := func(e ast.NavigableExpr) bool { return opt.constantExprMatcher(ctx, a, e) } foldableExprs := ast.MatchDescendants(root, constantExprMatcherCapture) foldCount := 0 for len(foldableExprs) != 0 && foldCount < opt.maxFoldIterations { @@ -83,8 +101,10 @@ func (opt *constantFoldingOptimizer) Optimize(ctx *OptimizerContext, a *ast.AST) continue } // Otherwise, assume all context is needed to evaluate the expression. - err := tryFold(ctx, a, fold) - if err != nil { + err := opt.tryFold(ctx, a, fold) + // Ignore errors for identifiers, since there is no guarantee that the environment + // has a value for them. + if err != nil && fold.Kind() != ast.IdentKind { ctx.ReportErrorAtID(fold.ID(), "constant-folding evaluation failed: %v", err.Error()) return a } @@ -96,7 +116,7 @@ func (opt *constantFoldingOptimizer) Optimize(ctx *OptimizerContext, a *ast.AST) // one last time. In this case, there's no guarantee they'll run, so we only update the // target comprehension node with the literal value if the evaluation succeeds. for _, compre := range ast.MatchDescendants(root, ast.KindMatcher(ast.ComprehensionKind)) { - tryFold(ctx, a, compre) + opt.tryFold(ctx, a, compre) } // If the output is a list, map, or struct which contains optional entries, then prune it @@ -126,7 +146,7 @@ func (opt *constantFoldingOptimizer) Optimize(ctx *OptimizerContext, a *ast.AST) // // If the evaluation succeeds, the input expr value will be modified to become a literal, otherwise // the method will return an error. -func tryFold(ctx *OptimizerContext, a *ast.AST, expr ast.Expr) error { +func (opt *constantFoldingOptimizer) tryFold(ctx *OptimizerContext, a *ast.AST, expr ast.Expr) error { // Assume all context is needed to evaluate the expression. subAST := &Ast{ impl: ast.NewCheckedAST(ast.NewAST(expr, a.SourceInfo()), a.TypeMap(), a.ReferenceMap()), @@ -135,7 +155,11 @@ func tryFold(ctx *OptimizerContext, a *ast.AST, expr ast.Expr) error { if err != nil { return err } - out, _, err := prg.Eval(NoVars()) + activation := opt.knownValues + if activation == nil { + activation = NoVars() + } + out, _, err := prg.Eval(activation) if err != nil { return err } @@ -469,13 +493,15 @@ func adaptLiteral(ctx *OptimizerContext, val ref.Val) (ast.Expr, error) { // Only comprehensions which are not nested are included as possible constant folds, and only // if all variables referenced in the comprehension stack exist are only iteration or // accumulation variables. -func constantExprMatcher(ctx *OptimizerContext, a *ast.AST, e ast.NavigableExpr) bool { +func (opt *constantFoldingOptimizer) constantExprMatcher(ctx *OptimizerContext, a *ast.AST, e ast.NavigableExpr) bool { switch e.Kind() { case ast.CallKind: return constantCallMatcher(e) case ast.SelectKind: sel := e.AsSelect() // guaranteed to be a navigable value return constantMatcher(sel.Operand().(ast.NavigableExpr)) + case ast.IdentKind: + return opt.knownValues != nil && a.ReferenceMap()[e.ID()] != nil case ast.ComprehensionKind: if isNestedComprehension(e) { return false diff --git a/vendor/github.com/google/cel-go/cel/io.go b/vendor/github.com/google/cel-go/cel/io.go index 7b1a4bed2..2e611228d 100644 --- a/vendor/github.com/google/cel-go/cel/io.go +++ b/vendor/github.com/google/cel-go/cel/io.go @@ -126,6 +126,55 @@ func ValueAsAlphaProto(res ref.Val) (*exprpb.Value, error) { return alpha, err } +// RefValToExprValue converts between ref.Val and google.api.expr.v1alpha1.ExprValue. +// The result ExprValue is the serialized proto form. +func RefValToExprValue(res ref.Val) (*exprpb.ExprValue, error) { + return ExprValueAsAlphaProto(res) +} + +// ExprValueAsAlphaProto converts between ref.Val and google.api.expr.v1alpha1.ExprValue. +// The result ExprValue is the serialized proto form. +func ExprValueAsAlphaProto(res ref.Val) (*exprpb.ExprValue, error) { + canonical, err := ExprValueAsProto(res) + if err != nil { + return nil, err + } + alpha := &exprpb.ExprValue{} + err = convertProto(canonical, alpha) + return alpha, err +} + +// ExprValueAsProto converts between ref.Val and cel.expr.ExprValue. +// The result ExprValue is the serialized proto form. +func ExprValueAsProto(res ref.Val) (*celpb.ExprValue, error) { + switch res := res.(type) { + case *types.Unknown: + return &celpb.ExprValue{ + Kind: &celpb.ExprValue_Unknown{ + Unknown: &celpb.UnknownSet{ + Exprs: res.IDs(), + }, + }}, nil + case *types.Err: + return &celpb.ExprValue{ + Kind: &celpb.ExprValue_Error{ + Error: &celpb.ErrorSet{ + // Keeping the error code as UNKNOWN since there's no error codes associated with + // Cel-Go runtime errors. + Errors: []*celpb.Status{{Code: 2, Message: res.Error()}}, + }, + }, + }, nil + default: + val, err := ValueAsProto(res) + if err != nil { + return nil, err + } + return &celpb.ExprValue{ + Kind: &celpb.ExprValue_Value{Value: val}}, nil + } +} + // ValueAsProto converts between ref.Val and cel.expr.Value. // The result Value is the serialized proto form. The ref.Val must not be error or unknown. func ValueAsProto(res ref.Val) (*celpb.Value, error) { diff --git a/vendor/github.com/google/cel-go/checker/checker.go b/vendor/github.com/google/cel-go/checker/checker.go index a9e04fc26..0057c16cc 100644 --- a/vendor/github.com/google/cel-go/checker/checker.go +++ b/vendor/github.com/google/cel-go/checker/checker.go @@ -152,7 +152,7 @@ func (c *checker) checkOptSelect(e ast.Expr) { } c.errors.notAnOptionalFieldSelectionCall(e.ID(), c.location(e), fmt.Sprintf( - "incorrect signature.%s argument count: %d%s", t, len(call.Args()))) + "incorrect signature.%s argument count: %d", t, len(call.Args()))) return } diff --git a/vendor/github.com/google/cel-go/checker/cost.go b/vendor/github.com/google/cel-go/checker/cost.go index 59be751c9..5bc6318ed 100644 --- a/vendor/github.com/google/cel-go/checker/cost.go +++ b/vendor/github.com/google/cel-go/checker/cost.go @@ -545,16 +545,17 @@ func (c *coster) costCall(e ast.Expr) CostEstimate { if len(overloadIDs) == 0 { return CostEstimate{} } - var targetType AstNode + var targetType *AstNode if call.IsMemberFunction() { sum = sum.Add(c.cost(call.Target())) - targetType = c.newAstNode(call.Target()) + var t AstNode = c.newAstNode(call.Target()) + targetType = &t } // Pick a cost estimate range that covers all the overload cost estimation ranges fnCost := CostEstimate{Min: uint64(math.MaxUint64), Max: 0} var resultSize *SizeEstimate for _, overload := range overloadIDs { - overloadCost := c.functionCost(e, call.FunctionName(), overload, &targetType, argTypes, argCosts) + overloadCost := c.functionCost(e, call.FunctionName(), overload, targetType, argTypes, argCosts) fnCost = fnCost.Union(overloadCost.CostEstimate) if overloadCost.ResultSize != nil { if resultSize == nil { diff --git a/vendor/github.com/google/cel-go/common/decls/decls.go b/vendor/github.com/google/cel-go/common/decls/decls.go index 759b1d16b..a4a51c3f2 100644 --- a/vendor/github.com/google/cel-go/common/decls/decls.go +++ b/vendor/github.com/google/cel-go/common/decls/decls.go @@ -303,7 +303,7 @@ func (f *FunctionDecl) OverloadDecls() []*OverloadDecl { return overloads } -// Returns true if the function has late bindings. A function cannot mix late bindings with other bindings. +// HasLateBinding returns true if the function has late bindings. A function cannot mix late bindings with other bindings. func (f *FunctionDecl) HasLateBinding() bool { if f == nil { return false diff --git a/vendor/github.com/google/cel-go/ext/BUILD.bazel b/vendor/github.com/google/cel-go/ext/BUILD.bazel index 24066b864..ef4f4ec3d 100644 --- a/vendor/github.com/google/cel-go/ext/BUILD.bazel +++ b/vendor/github.com/google/cel-go/ext/BUILD.bazel @@ -18,6 +18,7 @@ go_library( "math.go", "native.go", "protos.go", + "regex.go", "sets.go", "strings.go", ], @@ -26,6 +27,7 @@ go_library( deps = [ "//cel:go_default_library", "//checker:go_default_library", + "//common:go_default_library", "//common/ast:go_default_library", "//common/decls:go_default_library", "//common/env:go_default_library", @@ -59,6 +61,7 @@ go_test( "math_test.go", "native_test.go", "protos_test.go", + "regex_test.go", "sets_test.go", "strings_test.go", ], @@ -68,6 +71,7 @@ go_test( deps = [ "//cel:go_default_library", "//checker:go_default_library", + "//common:go_default_library", "//common/env:go_default_library", "//common/types:go_default_library", "//common/types/ref:go_default_library", diff --git a/vendor/github.com/google/cel-go/ext/README.md b/vendor/github.com/google/cel-go/ext/README.md index 4620204fc..41ae6a314 100644 --- a/vendor/github.com/google/cel-go/ext/README.md +++ b/vendor/github.com/google/cel-go/ext/README.md @@ -356,6 +356,23 @@ Examples: math.isFinite(0.0/0.0) // returns false math.isFinite(1.2) // returns true +### Math.Sqrt + +Introduced at version: 2 + +Returns the square root of the given input as double +Throws error for negative or non-numeric inputs + + math.sqrt() -> + math.sqrt() -> + math.sqrt() -> + +Examples: + + math.sqrt(81) // returns 9.0 + math.sqrt(985.25) // returns 31.388692231439016 + math.sqrt(-15) // returns NaN + ## Protos Protos configure extended macros and functions for proto manipulation. @@ -395,7 +412,7 @@ zero-based. ### Distinct -**Introduced in version 2** +**Introduced in version 2 (cost support in version 3)** Returns the distinct elements of a list. @@ -409,7 +426,7 @@ Examples: ### Flatten -**Introduced in version 1** +**Introduced in version 1 (cost support in version 3)** Flattens a list recursively. If an optional depth is provided, the list is flattened to a the specificied level. @@ -428,7 +445,7 @@ Examples: ### Range -**Introduced in version 2** +**Introduced in version 2 (cost support in version 3)** Returns a list of integers from 0 to n-1. @@ -441,7 +458,7 @@ Examples: ### Reverse -**Introduced in version 2** +**Introduced in version 2 (cost support in version 3)** Returns the elements of a list in reverse order. @@ -454,6 +471,7 @@ Examples: ### Slice +**Introduced in version 0 (cost support in version 3)** Returns a new sub-list using the indexes provided. @@ -466,7 +484,7 @@ Examples: ### Sort -**Introduced in version 2** +**Introduced in version 2 (cost support in version 3)** Sorts a list with comparable elements. If the element type is not comparable or the element types are not the same, the function will produce an error. @@ -483,7 +501,7 @@ Examples: ### SortBy -**Introduced in version 2** +**Introduced in version 2 (cost support in version 3)** Sorts a list by a key value, i.e., the order is determined by the result of an expression applied to each element of the list. diff --git a/vendor/github.com/google/cel-go/ext/extension_option_factory.go b/vendor/github.com/google/cel-go/ext/extension_option_factory.go index 4906227a5..cebf0d760 100644 --- a/vendor/github.com/google/cel-go/ext/extension_option_factory.go +++ b/vendor/github.com/google/cel-go/ext/extension_option_factory.go @@ -69,4 +69,7 @@ var extFactories = map[string]extensionFactory{ "two-var-comprehensions": func(version uint32) cel.EnvOption { return TwoVarComprehensions(TwoVarComprehensionsVersion(version)) }, + "regex": func(version uint32) cel.EnvOption { + return Regex(RegexVersion(version)) + }, } diff --git a/vendor/github.com/google/cel-go/ext/lists.go b/vendor/github.com/google/cel-go/ext/lists.go index 9a3cce37e..b27ddf22f 100644 --- a/vendor/github.com/google/cel-go/ext/lists.go +++ b/vendor/github.com/google/cel-go/ext/lists.go @@ -20,11 +20,14 @@ import ( "sort" "github.com/google/cel-go/cel" + "github.com/google/cel-go/checker" + "github.com/google/cel-go/common" "github.com/google/cel-go/common/ast" "github.com/google/cel-go/common/decls" "github.com/google/cel-go/common/types" "github.com/google/cel-go/common/types/ref" "github.com/google/cel-go/common/types/traits" + "github.com/google/cel-go/interpreter" "github.com/google/cel-go/parser" ) @@ -44,7 +47,7 @@ var comparableTypes = []*cel.Type{ // // # Distinct // -// Introduced in version: 2 +// Introduced in version: 2 (cost support in version 3) // // Returns the distinct elements of a list. // @@ -58,7 +61,7 @@ var comparableTypes = []*cel.Type{ // // # Range // -// Introduced in version: 2 +// Introduced in version: 2 (cost support in version 3) // // Returns a list of integers from 0 to n-1. // @@ -70,7 +73,7 @@ var comparableTypes = []*cel.Type{ // // # Reverse // -// Introduced in version: 2 +// Introduced in version: 2 (cost support in version 3) // // Returns the elements of a list in reverse order. // @@ -82,6 +85,8 @@ var comparableTypes = []*cel.Type{ // // # Slice // +// Introduced in version: 0 (cost support in version 3) +// // Returns a new sub-list using the indexes provided. // // .slice(, ) -> @@ -93,12 +98,14 @@ var comparableTypes = []*cel.Type{ // // # Flatten // +// Introduced in version: 1 (cost support in version 3) +// // Flattens a list recursively. -// If an optional depth is provided, the list is flattened to a the specificied level. +// If an optional depth is provided, the list is flattened to a the specified level. // A negative depth value will result in an error. // -// .flatten() -> -// .flatten(, ) -> +// .flatten() -> +// .flatten() -> // // Examples: // @@ -110,7 +117,7 @@ var comparableTypes = []*cel.Type{ // // # Sort // -// Introduced in version: 2 +// Introduced in version: 2 (cost support in version 3) // // Sorts a list with comparable elements. If the element type is not comparable // or the element types are not the same, the function will produce an error. @@ -127,6 +134,8 @@ var comparableTypes = []*cel.Type{ // // # SortBy // +// Introduced in version: 2 (cost support in version 3) +// // Sorts a list by a key value, i.e., the order is determined by the result of // an expression applied to each element of the list. // The output of the key expression must be a comparable type, otherwise the @@ -303,9 +312,8 @@ func (lib listsLib) CompileOptions() []cel.EnvOption { opts = append(opts, cel.Function("lists.range", cel.Overload("lists_range", []*cel.Type{cel.IntType}, cel.ListType(cel.IntType), - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - n := args[0].(types.Int) - result, err := genRange(n) + cel.UnaryBinding(func(n ref.Val) ref.Val { + result, err := genRange(n.(types.Int)) if err != nil { return types.WrapErr(err) } @@ -316,9 +324,8 @@ func (lib listsLib) CompileOptions() []cel.EnvOption { opts = append(opts, cel.Function("reverse", cel.MemberOverload("list_reverse", []*cel.Type{listType}, listType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - list := args[0].(traits.Lister) - result, err := reverseList(list) + cel.UnaryBinding(func(list ref.Val) ref.Val { + result, err := reverseList(list.(traits.Lister)) if err != nil { return types.WrapErr(err) } @@ -339,13 +346,61 @@ func (lib listsLib) CompileOptions() []cel.EnvOption { ), )) } + if lib.version >= 3 { + estimators := []checker.CostOption{ + checker.OverloadCostEstimate("list_slice", estimateListSlice), + checker.OverloadCostEstimate("list_flatten", estimateListFlatten), + checker.OverloadCostEstimate("list_flatten_int", estimateListFlatten), + checker.OverloadCostEstimate("lists_range", estimateListsRange), + checker.OverloadCostEstimate("list_reverse", estimateListReverse), + checker.OverloadCostEstimate("list_distinct", estimateListDistinct), + } + for _, t := range comparableTypes { + estimators = append(estimators, + checker.OverloadCostEstimate( + fmt.Sprintf("list_%s_sort", t.TypeName()), + estimateListSort(t), + ), + checker.OverloadCostEstimate( + fmt.Sprintf("list_%s_sortByAssociatedKeys", t.TypeName()), + estimateListSortBy(t), + ), + ) + } + opts = append(opts, cel.CostEstimatorOptions(estimators...)) + } return opts } // ProgramOptions implements the Library interface method. -func (listsLib) ProgramOptions() []cel.ProgramOption { - return []cel.ProgramOption{} +func (lib *listsLib) ProgramOptions() []cel.ProgramOption { + var opts []cel.ProgramOption + if lib.version >= 3 { + // TODO: Add cost trackers for list operations + trackers := []interpreter.CostTrackerOption{ + interpreter.OverloadCostTracker("list_slice", trackListOutputSize), + interpreter.OverloadCostTracker("list_flatten", trackListFlatten), + interpreter.OverloadCostTracker("list_flatten_int", trackListFlatten), + interpreter.OverloadCostTracker("lists_range", trackListOutputSize), + interpreter.OverloadCostTracker("list_reverse", trackListOutputSize), + interpreter.OverloadCostTracker("list_distinct", trackListDistinct), + } + for _, t := range comparableTypes { + trackers = append(trackers, + interpreter.OverloadCostTracker( + fmt.Sprintf("list_%s_sort", t.TypeName()), + trackListSort, + ), + interpreter.OverloadCostTracker( + fmt.Sprintf("list_%s_sortByAssociatedKeys", t.TypeName()), + trackListSortBy, + ), + ) + } + opts = append(opts, cel.CostTrackerOptions(trackers...)) + } + return opts } func genRange(n types.Int) (ref.Val, error) { @@ -450,20 +505,24 @@ func sortListByAssociatedKeys(list, keys traits.Lister) (ref.Val, error) { sortedIndices := make([]ref.Val, 0, listLength) for i := types.IntZero; i < listLength; i++ { - if keys.Get(i).Type() != elem.Type() { - return nil, fmt.Errorf("list elements must have the same type") - } sortedIndices = append(sortedIndices, i) } + var err error sort.Slice(sortedIndices, func(i, j int) bool { iKey := keys.Get(sortedIndices[i]) jKey := keys.Get(sortedIndices[j]) + if iKey.Type() != elem.Type() || jKey.Type() != elem.Type() { + err = fmt.Errorf("list elements must have the same type") + return false + } return iKey.(traits.Comparer).Compare(jKey) == types.IntNegOne }) + if err != nil { + return nil, err + } sorted := make([]ref.Val, 0, listLength) - for _, sortedIdx := range sortedIndices { sorted = append(sorted, list.Get(sortedIdx)) } @@ -550,3 +609,171 @@ func templatedOverloads(types []*cel.Type, template func(t *cel.Type) cel.Functi } return overloads } + +// estimateListSlice computes an O(n) slice operation with a cost factor of 1. +func estimateListSlice(estimator checker.CostEstimator, target *checker.AstNode, args []checker.AstNode) *checker.CallEstimate { + if target == nil || len(args) != 2 { + return nil + } + sz := estimateSize(estimator, *target) + start := nodeAsIntValue(args[0], 0) + end := nodeAsIntValue(args[1], sz.Max) + return estimateAllocatingListCall(1, checker.FixedSizeEstimate(end-start)) +} + +// estimateListsRange computes an O(n) range operation with a cost factor of 1. +func estimateListsRange(estimator checker.CostEstimator, target *checker.AstNode, args []checker.AstNode) *checker.CallEstimate { + if target != nil || len(args) != 1 { + return nil + } + return estimateAllocatingListCall(1, checker.FixedSizeEstimate(nodeAsIntValue(args[0], math.MaxUint))) +} + +// estimateListReverse computes an O(n) reverse operation with a cost factor of 1. +func estimateListReverse(estimator checker.CostEstimator, target *checker.AstNode, args []checker.AstNode) *checker.CallEstimate { + if target == nil || len(args) != 0 { + return nil + } + return estimateAllocatingListCall(1, estimateSize(estimator, *target)) +} + +// estimateListFlatten computes an O(n) flatten operation with a cost factor proportional to the flatten depth. +func estimateListFlatten(estimator checker.CostEstimator, target *checker.AstNode, args []checker.AstNode) *checker.CallEstimate { + if target == nil || len(args) > 1 { + return nil + } + depth := uint64(1) + if len(args) == 1 { + depth = nodeAsIntValue(args[0], math.MaxUint) + } + return estimateAllocatingListCall(float64(depth), estimateSize(estimator, *target)) +} + +// Compute an O(n^2) with a cost factor of 2, equivalent to sets.contains with a result list +// which can vary in size from 1 element to the original list size. +func estimateListDistinct(estimator checker.CostEstimator, target *checker.AstNode, args []checker.AstNode) *checker.CallEstimate { + if target == nil || len(args) != 0 { + return nil + } + sz := estimateSize(estimator, *target) + costFactor := 2.0 + return estimateAllocatingListCall(costFactor, sz.Multiply(sz)) +} + +// estimateListSort computes an O(n^2) sort operation with a cost factor of 2 for the equality +// operations against the elements in the list against themselves which occur during the sort computation. +func estimateListSort(t *types.Type) checker.FunctionEstimator { + return func(estimator checker.CostEstimator, target *checker.AstNode, args []checker.AstNode) *checker.CallEstimate { + if target == nil || len(args) != 0 { + return nil + } + return estimateListSortCost(estimator, *target, t) + } +} + +// estimateListSortBy computes an O(n^2) sort operation with a cost factor of 2 for the equality +// operations against the sort index list which occur during the sort computation. +func estimateListSortBy(u *types.Type) checker.FunctionEstimator { + return func(estimator checker.CostEstimator, target *checker.AstNode, args []checker.AstNode) *checker.CallEstimate { + if target == nil || len(args) != 1 { + return nil + } + // Estimate the size of the list used as the sort index + return estimateListSortCost(estimator, args[0], u) + } +} + +// estimateListSortCost estimates an O(n^2) sort operation with a cost factor of 2 for the equality +// operations which occur during the sort computation. +func estimateListSortCost(estimator checker.CostEstimator, node checker.AstNode, elemType *types.Type) *checker.CallEstimate { + sz := estimateSize(estimator, node) + costFactor := 2.0 + switch elemType { + case types.StringType, types.BytesType: + costFactor += common.StringTraversalCostFactor + } + return estimateAllocatingListCall(costFactor, sz.Multiply(sz)) +} + +// estimateAllocatingListCall computes cost as a function of the size of the result list with a +// baseline cost for the call dispatch and the associated list allocation. +func estimateAllocatingListCall(costFactor float64, listSize checker.SizeEstimate) *checker.CallEstimate { + return estimateListCall(costFactor, listSize, true) +} + +// estimateListCall computes cost as a function of the size of the target list and whether the +// call allocates memory. +func estimateListCall(costFactor float64, listSize checker.SizeEstimate, allocates bool) *checker.CallEstimate { + cost := listSize.MultiplyByCostFactor(costFactor).Add(callCostEstimate) + if allocates { + cost = cost.Add(checker.FixedCostEstimate(common.ListCreateBaseCost)) + } + return &checker.CallEstimate{CostEstimate: cost, ResultSize: &listSize} +} + +// trackListOutputSize computes cost as a function of the size of the result list. +func trackListOutputSize(_ []ref.Val, result ref.Val) *uint64 { + return trackAllocatingListCall(1, actualSize(result)) +} + +// trackListFlatten computes cost as a function of the size of the result list and the depth of +// the flatten operation. +func trackListFlatten(args []ref.Val, _ ref.Val) *uint64 { + depth := 1.0 + if len(args) == 2 { + depth = float64(args[1].(types.Int)) + } + inputSize := actualSize(args[0]) + return trackAllocatingListCall(depth, inputSize) +} + +// trackListDistinct computes costs as a worst-case O(n^2) operation over the input list. +func trackListDistinct(args []ref.Val, _ ref.Val) *uint64 { + return trackListSelfCompare(args[0].(traits.Lister)) +} + +// trackListSort computes costs as a worst-case O(n^2) operation over the input list. +func trackListSort(args []ref.Val, result ref.Val) *uint64 { + return trackListSelfCompare(args[0].(traits.Lister)) +} + +// trackListSortBy computes costs as a worst-case O(n^2) operation over the sort index list. +func trackListSortBy(args []ref.Val, result ref.Val) *uint64 { + return trackListSelfCompare(args[1].(traits.Lister)) +} + +// trackListSelfCompare computes costs as a worst-case O(n^2) operation over the input list. +func trackListSelfCompare(l traits.Lister) *uint64 { + sz := actualSize(l) + costFactor := 2.0 + if sz == 0 { + return trackAllocatingListCall(costFactor, 0) + } + elem := l.Get(types.IntZero) + if elem.Type() == types.StringType || elem.Type() == types.BytesType { + costFactor += common.StringTraversalCostFactor + } + return trackAllocatingListCall(costFactor, sz*sz) +} + +// trackAllocatingListCall computes costs as a function of the size of the result list with a baseline cost +// for the call dispatch and the associated list allocation. +func trackAllocatingListCall(costFactor float64, size uint64) *uint64 { + cost := uint64(float64(size)*costFactor) + callCost + common.ListCreateBaseCost + return &cost +} + +func nodeAsIntValue(node checker.AstNode, defaultVal uint64) uint64 { + if node.Expr().Kind() != ast.LiteralKind { + return defaultVal + } + lit := node.Expr().AsLiteral() + if lit.Type() != types.IntType { + return defaultVal + } + val := lit.(types.Int) + if val < types.IntZero { + return 0 + } + return uint64(lit.(types.Int)) +} diff --git a/vendor/github.com/google/cel-go/ext/math.go b/vendor/github.com/google/cel-go/ext/math.go index 250246db1..6df8e3773 100644 --- a/vendor/github.com/google/cel-go/ext/math.go +++ b/vendor/github.com/google/cel-go/ext/math.go @@ -325,6 +325,23 @@ import ( // // math.isFinite(0.0/0.0) // returns false // math.isFinite(1.2) // returns true +// +// # Math.Sqrt +// +// Introduced at version: 2 +// +// Returns the square root of the given input as double +// Throws error for negative or non-numeric inputs +// +// math.sqrt() -> +// math.sqrt() -> +// math.sqrt() -> +// +// Examples: +// +// math.sqrt(81) // returns 9.0 +// math.sqrt(985.25) // returns 31.388692231439016 +// math.sqrt(-15) // returns NaN func Math(options ...MathOption) cel.EnvOption { m := &mathLib{version: math.MaxUint32} for _, o := range options { @@ -357,6 +374,9 @@ const ( absFunc = "math.abs" signFunc = "math.sign" + // SquareRoot function + sqrtFunc = "math.sqrt" + // Bitwise functions bitAndFunc = "math.bitAnd" bitOrFunc = "math.bitOr" @@ -548,6 +568,18 @@ func (lib *mathLib) CompileOptions() []cel.EnvOption { ), ) } + if lib.version >= 2 { + opts = append(opts, + cel.Function(sqrtFunc, + cel.Overload("math_sqrt_double", []*cel.Type{cel.DoubleType}, cel.DoubleType, + cel.UnaryBinding(sqrt)), + cel.Overload("math_sqrt_int", []*cel.Type{cel.IntType}, cel.DoubleType, + cel.UnaryBinding(sqrt)), + cel.Overload("math_sqrt_uint", []*cel.Type{cel.UintType}, cel.DoubleType, + cel.UnaryBinding(sqrt)), + ), + ) + } return opts } @@ -691,6 +723,21 @@ func sign(val ref.Val) ref.Val { } } + +func sqrt(val ref.Val) ref.Val { + switch v := val.(type) { + case types.Double: + return types.Double(math.Sqrt(float64(v))) + case types.Int: + return types.Double(math.Sqrt(float64(v))) + case types.Uint: + return types.Double(math.Sqrt(float64(v))) + default: + return types.NewErr("no such overload: sqrt") + } +} + + func bitAndPairInt(first, second ref.Val) ref.Val { l := first.(types.Int) r := second.(types.Int) diff --git a/vendor/github.com/google/cel-go/ext/regex.go b/vendor/github.com/google/cel-go/ext/regex.go new file mode 100644 index 000000000..1a66f65d0 --- /dev/null +++ b/vendor/github.com/google/cel-go/ext/regex.go @@ -0,0 +1,332 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ext + +import ( + "errors" + "fmt" + "math" + "regexp" + "strconv" + "strings" + + "github.com/google/cel-go/cel" + "github.com/google/cel-go/common/types" + "github.com/google/cel-go/common/types/ref" +) + +const ( + regexReplace = "regex.replace" + regexExtract = "regex.extract" + regexExtractAll = "regex.extractAll" +) + +// Regex returns a cel.EnvOption to configure extended functions for regular +// expression operations. +// +// Note: all functions use the 'regex' namespace. If you are +// currently using a variable named 'regex', the functions will likely work as +// intended, however there is some chance for collision. +// +// This library depends on the CEL optional type. Please ensure that the +// cel.OptionalTypes() is enabled when using regex extensions. +// +// # Replace +// +// The `regex.replace` function replaces all non-overlapping substring of a regex +// pattern in the target string with a replacement string. Optionally, you can +// limit the number of replacements by providing a count argument. When the count +// is a negative number, the function acts as replace all. Only numeric (\N) +// capture group references are supported in the replacement string, with +// validation for correctness. Backslashed-escaped digits (\1 to \9) within the +// replacement argument can be used to insert text matching the corresponding +// parenthesized group in the regexp pattern. An error will be thrown for invalid +// regex or replace string. +// +// regex.replace(target: string, pattern: string, replacement: string) -> string +// regex.replace(target: string, pattern: string, replacement: string, count: int) -> string +// +// Examples: +// +// regex.replace('hello world hello', 'hello', 'hi') == 'hi world hi' +// regex.replace('banana', 'a', 'x', 0) == 'banana' +// regex.replace('banana', 'a', 'x', 1) == 'bxnana' +// regex.replace('banana', 'a', 'x', 2) == 'bxnxna' +// regex.replace('banana', 'a', 'x', -12) == 'bxnxnx' +// regex.replace('foo bar', '(fo)o (ba)r', r'\2 \1') == 'ba fo' +// regex.replace('test', '(.)', r'\2') \\ Runtime Error invalid replace string +// regex.replace('foo bar', '(', '$2 $1') \\ Runtime Error invalid regex string +// regex.replace('id=123', r'id=(?P\d+)', r'value: \values') \\ Runtime Error invalid replace string +// +// # Extract +// +// The `regex.extract` function returns the first match of a regex pattern in a +// string. If no match is found, it returns an optional none value. An error will +// be thrown for invalid regex or for multiple capture groups. +// +// regex.extract(target: string, pattern: string) -> optional +// +// Examples: +// +// regex.extract('hello world', 'hello(.*)') == optional.of(' world') +// regex.extract('item-A, item-B', 'item-(\\w+)') == optional.of('A') +// regex.extract('HELLO', 'hello') == optional.empty() +// regex.extract('testuser@testdomain', '(.*)@([^.]*)') // Runtime Error multiple capture group +// +// # Extract All +// +// The `regex.extractAll` function returns a list of all matches of a regex +// pattern in a target string. If no matches are found, it returns an empty list. An error will +// be thrown for invalid regex or for multiple capture groups. +// +// regex.extractAll(target: string, pattern: string) -> list +// +// Examples: +// +// regex.extractAll('id:123, id:456', 'id:\\d+') == ['id:123', 'id:456'] +// regex.extractAll('id:123, id:456', 'assa') == [] +// regex.extractAll('testuser@testdomain', '(.*)@([^.]*)') // Runtime Error multiple capture group +func Regex(options ...RegexOptions) cel.EnvOption { + s := ®exLib{ + version: math.MaxUint32, + } + for _, o := range options { + s = o(s) + } + return cel.Lib(s) +} + +// RegexOptions declares a functional operator for configuring regex extension. +type RegexOptions func(*regexLib) *regexLib + +// RegexVersion configures the version of the Regex library definitions to use. See [Regex] for supported values. +func RegexVersion(version uint32) RegexOptions { + return func(lib *regexLib) *regexLib { + lib.version = version + return lib + } +} + +type regexLib struct { + version uint32 +} + +// LibraryName implements that SingletonLibrary interface method. +func (r *regexLib) LibraryName() string { + return "cel.lib.ext.regex" +} + +// CompileOptions implements the cel.Library interface method. +func (r *regexLib) CompileOptions() []cel.EnvOption { + optionalTypesEnabled := func(env *cel.Env) (*cel.Env, error) { + if !env.HasLibrary("cel.lib.optional") { + return nil, errors.New("regex library requires the optional library") + } + return env, nil + } + opts := []cel.EnvOption{ + cel.Function(regexExtract, + cel.Overload("regex_extract_string_string", []*cel.Type{cel.StringType, cel.StringType}, cel.OptionalType(cel.StringType), + cel.BinaryBinding(extract))), + + cel.Function(regexExtractAll, + cel.Overload("regex_extractAll_string_string", []*cel.Type{cel.StringType, cel.StringType}, cel.ListType(cel.StringType), + cel.BinaryBinding(extractAll))), + + cel.Function(regexReplace, + cel.Overload("regex_replace_string_string_string", []*cel.Type{cel.StringType, cel.StringType, cel.StringType}, cel.StringType, + cel.FunctionBinding(regReplace)), + cel.Overload("regex_replace_string_string_string_int", []*cel.Type{cel.StringType, cel.StringType, cel.StringType, cel.IntType}, cel.StringType, + cel.FunctionBinding((regReplaceN))), + ), + cel.EnvOption(optionalTypesEnabled), + } + return opts +} + +// ProgramOptions implements the cel.Library interface method +func (r *regexLib) ProgramOptions() []cel.ProgramOption { + return []cel.ProgramOption{} +} + +func compileRegex(regexStr string) (*regexp.Regexp, error) { + re, err := regexp.Compile(regexStr) + if err != nil { + return nil, fmt.Errorf("given regex is invalid: %w", err) + } + return re, nil +} + +func regReplace(args ...ref.Val) ref.Val { + target := args[0].(types.String) + regexStr := args[1].(types.String) + replaceStr := args[2].(types.String) + + return regReplaceN(target, regexStr, replaceStr, types.Int(-1)) +} + +func regReplaceN(args ...ref.Val) ref.Val { + target := string(args[0].(types.String)) + regexStr := string(args[1].(types.String)) + replaceStr := string(args[2].(types.String)) + replaceCount := int64(args[3].(types.Int)) + + if replaceCount == 0 { + return types.String(target) + } + + if replaceCount > math.MaxInt32 { + return types.NewErr("integer overflow") + } + + // If replaceCount is negative, just do a replaceAll. + if replaceCount < 0 { + replaceCount = -1 + } + + re, err := regexp.Compile(regexStr) + if err != nil { + return types.WrapErr(err) + } + + var resultBuilder strings.Builder + var lastIndex int + counter := int64(0) + + matches := re.FindAllStringSubmatchIndex(target, -1) + + for _, match := range matches { + if replaceCount != -1 && counter >= replaceCount { + break + } + + processedReplacement, err := replaceStrValidator(target, re, match, replaceStr) + if err != nil { + return types.WrapErr(err) + } + + resultBuilder.WriteString(target[lastIndex:match[0]]) + resultBuilder.WriteString(processedReplacement) + lastIndex = match[1] + counter++ + } + + resultBuilder.WriteString(target[lastIndex:]) + return types.String(resultBuilder.String()) +} + +func replaceStrValidator(target string, re *regexp.Regexp, match []int, replacement string) (string, error) { + groupCount := re.NumSubexp() + var sb strings.Builder + runes := []rune(replacement) + + for i := 0; i < len(runes); i++ { + c := runes[i] + + if c != '\\' { + sb.WriteRune(c) + continue + } + + if i+1 >= len(runes) { + return "", fmt.Errorf("invalid replacement string: '%s' \\ not allowed at end", replacement) + } + + i++ + nextChar := runes[i] + + if nextChar == '\\' { + sb.WriteRune('\\') + continue + } + + groupNum, err := strconv.Atoi(string(nextChar)) + if err != nil { + return "", fmt.Errorf("invalid replacement string: '%s' \\ must be followed by a digit or \\", replacement) + } + + if groupNum > groupCount { + return "", fmt.Errorf("replacement string references group %d but regex has only %d group(s)", groupNum, groupCount) + } + + if match[2*groupNum] != -1 { + sb.WriteString(target[match[2*groupNum]:match[2*groupNum+1]]) + } + } + return sb.String(), nil +} + +func extract(target, regexStr ref.Val) ref.Val { + t := string(target.(types.String)) + r := string(regexStr.(types.String)) + re, err := compileRegex(r) + if err != nil { + return types.WrapErr(err) + } + + if len(re.SubexpNames())-1 > 1 { + return types.WrapErr(fmt.Errorf("regular expression has more than one capturing group: %q", r)) + } + + matches := re.FindStringSubmatch(t) + if len(matches) == 0 { + return types.OptionalNone + } + + // If there is a capturing group, return the first match; otherwise, return the whole match. + if len(matches) > 1 { + capturedGroup := matches[1] + // If optional group is empty, return OptionalNone. + if capturedGroup == "" { + return types.OptionalNone + } + return types.OptionalOf(types.String(capturedGroup)) + } + return types.OptionalOf(types.String(matches[0])) +} + +func extractAll(target, regexStr ref.Val) ref.Val { + t := string(target.(types.String)) + r := string(regexStr.(types.String)) + re, err := compileRegex(r) + if err != nil { + return types.WrapErr(err) + } + + groupCount := len(re.SubexpNames()) - 1 + if groupCount > 1 { + return types.WrapErr(fmt.Errorf("regular expression has more than one capturing group: %q", r)) + } + + matches := re.FindAllStringSubmatch(t, -1) + result := make([]string, 0, len(matches)) + if len(matches) == 0 { + return types.NewStringList(types.DefaultTypeAdapter, result) + } + + if groupCount != 1 { + for _, match := range matches { + result = append(result, match[0]) + } + return types.NewStringList(types.DefaultTypeAdapter, result) + } + + for _, match := range matches { + if match[1] != "" { + result = append(result, match[1]) + } + } + return types.NewStringList(types.DefaultTypeAdapter, result) +} diff --git a/vendor/github.com/google/cel-go/ext/sets.go b/vendor/github.com/google/cel-go/ext/sets.go index 9a9ef6eef..ecac4bf9d 100644 --- a/vendor/github.com/google/cel-go/ext/sets.go +++ b/vendor/github.com/google/cel-go/ext/sets.go @@ -236,13 +236,13 @@ func setsEquivalent(listA, listB ref.Val) ref.Val { func estimateSetsCost(costFactor float64) checker.FunctionEstimator { return func(estimator checker.CostEstimator, target *checker.AstNode, args []checker.AstNode) *checker.CallEstimate { - if len(args) == 2 { - arg0Size := estimateSize(estimator, args[0]) - arg1Size := estimateSize(estimator, args[1]) - costEstimate := arg0Size.Multiply(arg1Size).MultiplyByCostFactor(costFactor).Add(callCostEstimate) - return &checker.CallEstimate{CostEstimate: costEstimate} + if len(args) != 2 { + return nil } - return nil + arg0Size := estimateSize(estimator, args[0]) + arg1Size := estimateSize(estimator, args[1]) + costEstimate := arg0Size.Multiply(arg1Size).MultiplyByCostFactor(costFactor).Add(callCostEstimate) + return &checker.CallEstimate{CostEstimate: costEstimate} } } @@ -273,6 +273,6 @@ func actualSize(value ref.Val) uint64 { } var ( - callCostEstimate = checker.CostEstimate{Min: 1, Max: 1} + callCostEstimate = checker.FixedCostEstimate(1) callCost = uint64(1) ) diff --git a/vendor/github.com/google/cel-go/ext/strings.go b/vendor/github.com/google/cel-go/ext/strings.go index 88b4d7f03..de65421f6 100644 --- a/vendor/github.com/google/cel-go/ext/strings.go +++ b/vendor/github.com/google/cel-go/ext/strings.go @@ -607,6 +607,10 @@ func lastIndexOf(str, substr string) (int64, error) { if substr == "" { return int64(len(runes)), nil } + + if len(str) < len(substr) { + return -1, nil + } return lastIndexOfOffset(str, substr, int64(len(runes)-1)) } diff --git a/vendor/github.com/prometheus/client_golang/api/client.go b/vendor/github.com/prometheus/client_golang/api/client.go new file mode 100644 index 000000000..0e647b675 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/api/client.go @@ -0,0 +1,156 @@ +// Copyright 2015 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package api provides clients for the HTTP APIs. +package api + +import ( + "bytes" + "context" + "errors" + "net" + "net/http" + "net/url" + "path" + "strings" + "time" +) + +// DefaultRoundTripper is used if no RoundTripper is set in Config. +var DefaultRoundTripper http.RoundTripper = &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + }).DialContext, + TLSHandshakeTimeout: 10 * time.Second, +} + +// Config defines configuration parameters for a new client. +type Config struct { + // The address of the Prometheus to connect to. + Address string + + // Client is used by the Client to drive HTTP requests. If not provided, + // a new one based on the provided RoundTripper (or DefaultRoundTripper) will be used. + Client *http.Client + + // RoundTripper is used by the Client to drive HTTP requests. If not + // provided, DefaultRoundTripper will be used. + RoundTripper http.RoundTripper +} + +func (cfg *Config) roundTripper() http.RoundTripper { + if cfg.RoundTripper == nil { + return DefaultRoundTripper + } + return cfg.RoundTripper +} + +func (cfg *Config) client() http.Client { + if cfg.Client == nil { + return http.Client{ + Transport: cfg.roundTripper(), + } + } + return *cfg.Client +} + +func (cfg *Config) validate() error { + if cfg.Client != nil && cfg.RoundTripper != nil { + return errors.New("api.Config.RoundTripper and api.Config.Client are mutually exclusive") + } + return nil +} + +// Client is the interface for an API client. +type Client interface { + URL(ep string, args map[string]string) *url.URL + Do(context.Context, *http.Request) (*http.Response, []byte, error) +} + +type CloseIdler interface { + CloseIdleConnections() +} + +// NewClient returns a new Client. +// +// It is safe to use the returned Client from multiple goroutines. +func NewClient(cfg Config) (Client, error) { + u, err := url.Parse(cfg.Address) + if err != nil { + return nil, err + } + u.Path = strings.TrimRight(u.Path, "/") + + if err := cfg.validate(); err != nil { + return nil, err + } + + return &httpClient{ + endpoint: u, + client: cfg.client(), + }, nil +} + +type httpClient struct { + endpoint *url.URL + client http.Client +} + +func (c *httpClient) URL(ep string, args map[string]string) *url.URL { + p := path.Join(c.endpoint.Path, ep) + + for arg, val := range args { + arg = ":" + arg + p = strings.ReplaceAll(p, arg, val) + } + + u := *c.endpoint + u.Path = p + + return &u +} + +func (c *httpClient) CloseIdleConnections() { + c.client.CloseIdleConnections() +} + +func (c *httpClient) Do(ctx context.Context, req *http.Request) (*http.Response, []byte, error) { + if ctx != nil { + req = req.WithContext(ctx) + } + resp, err := c.client.Do(req) + if err != nil { + return nil, nil, err + } + + var body []byte + done := make(chan error, 1) + go func() { + var buf bytes.Buffer + _, err := buf.ReadFrom(resp.Body) + body = buf.Bytes() + done <- err + }() + + select { + case <-ctx.Done(): + resp.Body.Close() + <-done + return resp, nil, ctx.Err() + case err = <-done: + resp.Body.Close() + return resp, body, err + } +} diff --git a/vendor/github.com/prometheus/client_golang/api/prometheus/v1/api.go b/vendor/github.com/prometheus/client_golang/api/prometheus/v1/api.go new file mode 100644 index 000000000..8a72f9bfc --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/api/prometheus/v1/api.go @@ -0,0 +1,1502 @@ +// Copyright 2017 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package v1 provides bindings to the Prometheus HTTP API v1: +// http://prometheus.io/docs/querying/api/ +package v1 + +import ( + "context" + "errors" + "fmt" + "math" + "net/http" + "net/url" + "strconv" + "strings" + "time" + "unsafe" + + json "github.com/json-iterator/go" + + "github.com/prometheus/common/model" + + "github.com/prometheus/client_golang/api" +) + +func init() { + json.RegisterTypeEncoderFunc("model.SamplePair", marshalSamplePairJSON, marshalJSONIsEmpty) + json.RegisterTypeDecoderFunc("model.SamplePair", unmarshalSamplePairJSON) + json.RegisterTypeEncoderFunc("model.SampleHistogramPair", marshalSampleHistogramPairJSON, marshalJSONIsEmpty) + json.RegisterTypeDecoderFunc("model.SampleHistogramPair", unmarshalSampleHistogramPairJSON) + json.RegisterTypeEncoderFunc("model.SampleStream", marshalSampleStreamJSON, marshalJSONIsEmpty) // Only needed for benchmark. + json.RegisterTypeDecoderFunc("model.SampleStream", unmarshalSampleStreamJSON) // Only needed for benchmark. +} + +func unmarshalSamplePairJSON(ptr unsafe.Pointer, iter *json.Iterator) { + p := (*model.SamplePair)(ptr) + if !iter.ReadArray() { + iter.ReportError("unmarshal model.SamplePair", "SamplePair must be [timestamp, value]") + return + } + t := iter.ReadNumber() + if err := p.Timestamp.UnmarshalJSON([]byte(t)); err != nil { + iter.ReportError("unmarshal model.SamplePair", err.Error()) + return + } + if !iter.ReadArray() { + iter.ReportError("unmarshal model.SamplePair", "SamplePair missing value") + return + } + + f, err := strconv.ParseFloat(iter.ReadString(), 64) + if err != nil { + iter.ReportError("unmarshal model.SamplePair", err.Error()) + return + } + p.Value = model.SampleValue(f) + + if iter.ReadArray() { + iter.ReportError("unmarshal model.SamplePair", "SamplePair has too many values, must be [timestamp, value]") + return + } +} + +func marshalSamplePairJSON(ptr unsafe.Pointer, stream *json.Stream) { + p := *((*model.SamplePair)(ptr)) + stream.WriteArrayStart() + marshalTimestamp(p.Timestamp, stream) + stream.WriteMore() + marshalFloat(float64(p.Value), stream) + stream.WriteArrayEnd() +} + +func unmarshalSampleHistogramPairJSON(ptr unsafe.Pointer, iter *json.Iterator) { + p := (*model.SampleHistogramPair)(ptr) + if !iter.ReadArray() { + iter.ReportError("unmarshal model.SampleHistogramPair", "SampleHistogramPair must be [timestamp, {histogram}]") + return + } + t := iter.ReadNumber() + if err := p.Timestamp.UnmarshalJSON([]byte(t)); err != nil { + iter.ReportError("unmarshal model.SampleHistogramPair", err.Error()) + return + } + if !iter.ReadArray() { + iter.ReportError("unmarshal model.SampleHistogramPair", "SamplePair missing histogram") + return + } + h := &model.SampleHistogram{} + p.Histogram = h + for key := iter.ReadObject(); key != ""; key = iter.ReadObject() { + switch key { + case "count": + f, err := strconv.ParseFloat(iter.ReadString(), 64) + if err != nil { + iter.ReportError("unmarshal model.SampleHistogramPair", "count of histogram is not a float") + return + } + h.Count = model.FloatString(f) + case "sum": + f, err := strconv.ParseFloat(iter.ReadString(), 64) + if err != nil { + iter.ReportError("unmarshal model.SampleHistogramPair", "sum of histogram is not a float") + return + } + h.Sum = model.FloatString(f) + case "buckets": + for iter.ReadArray() { + b, err := unmarshalHistogramBucket(iter) + if err != nil { + iter.ReportError("unmarshal model.HistogramBucket", err.Error()) + return + } + h.Buckets = append(h.Buckets, b) + } + default: + iter.ReportError("unmarshal model.SampleHistogramPair", fmt.Sprint("unexpected key in histogram:", key)) + return + } + } + if iter.ReadArray() { + iter.ReportError("unmarshal model.SampleHistogramPair", "SampleHistogramPair has too many values, must be [timestamp, {histogram}]") + return + } +} + +func marshalSampleHistogramPairJSON(ptr unsafe.Pointer, stream *json.Stream) { + p := *((*model.SampleHistogramPair)(ptr)) + stream.WriteArrayStart() + marshalTimestamp(p.Timestamp, stream) + stream.WriteMore() + marshalHistogram(*p.Histogram, stream) + stream.WriteArrayEnd() +} + +func unmarshalSampleStreamJSON(ptr unsafe.Pointer, iter *json.Iterator) { + ss := (*model.SampleStream)(ptr) + for key := iter.ReadObject(); key != ""; key = iter.ReadObject() { + switch key { + case "metric": + metricString := iter.ReadAny().ToString() + if err := json.UnmarshalFromString(metricString, &ss.Metric); err != nil { + iter.ReportError("unmarshal model.SampleStream", err.Error()) + return + } + case "values": + for iter.ReadArray() { + v := model.SamplePair{} + unmarshalSamplePairJSON(unsafe.Pointer(&v), iter) + ss.Values = append(ss.Values, v) + } + case "histograms": + for iter.ReadArray() { + h := model.SampleHistogramPair{} + unmarshalSampleHistogramPairJSON(unsafe.Pointer(&h), iter) + ss.Histograms = append(ss.Histograms, h) + } + default: + iter.ReportError("unmarshal model.SampleStream", fmt.Sprint("unexpected key:", key)) + return + } + } +} + +func marshalSampleStreamJSON(ptr unsafe.Pointer, stream *json.Stream) { + ss := *((*model.SampleStream)(ptr)) + stream.WriteObjectStart() + stream.WriteObjectField(`metric`) + m, err := json.ConfigCompatibleWithStandardLibrary.Marshal(ss.Metric) + if err != nil { + stream.Error = err + return + } + stream.SetBuffer(append(stream.Buffer(), m...)) + if len(ss.Values) > 0 { + stream.WriteMore() + stream.WriteObjectField(`values`) + stream.WriteArrayStart() + for i, v := range ss.Values { + if i > 0 { + stream.WriteMore() + } + marshalSamplePairJSON(unsafe.Pointer(&v), stream) + } + stream.WriteArrayEnd() + } + if len(ss.Histograms) > 0 { + stream.WriteMore() + stream.WriteObjectField(`histograms`) + stream.WriteArrayStart() + for i, h := range ss.Histograms { + if i > 0 { + stream.WriteMore() + } + marshalSampleHistogramPairJSON(unsafe.Pointer(&h), stream) + } + stream.WriteArrayEnd() + } + stream.WriteObjectEnd() +} + +func marshalFloat(v float64, stream *json.Stream) { + stream.WriteRaw(`"`) + // Taken from https://github.com/json-iterator/go/blob/master/stream_float.go#L71 as a workaround + // to https://github.com/json-iterator/go/issues/365 (json-iterator, to follow json standard, doesn't allow inf/nan). + buf := stream.Buffer() + abs := math.Abs(v) + fmt := byte('f') + // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right. + if abs != 0 { + if abs < 1e-6 || abs >= 1e21 { + fmt = 'e' + } + } + buf = strconv.AppendFloat(buf, v, fmt, -1, 64) + stream.SetBuffer(buf) + stream.WriteRaw(`"`) +} + +func marshalTimestamp(timestamp model.Time, stream *json.Stream) { + t := int64(timestamp) + // Write out the timestamp as a float divided by 1000. + // This is ~3x faster than converting to a float. + if t < 0 { + stream.WriteRaw(`-`) + t = -t + } + stream.WriteInt64(t / 1000) + fraction := t % 1000 + if fraction != 0 { + stream.WriteRaw(`.`) + if fraction < 100 { + stream.WriteRaw(`0`) + } + if fraction < 10 { + stream.WriteRaw(`0`) + } + stream.WriteInt64(fraction) + } +} + +func unmarshalHistogramBucket(iter *json.Iterator) (*model.HistogramBucket, error) { + b := model.HistogramBucket{} + if !iter.ReadArray() { + return nil, errors.New("HistogramBucket must be [boundaries, lower, upper, count]") + } + boundaries, err := iter.ReadNumber().Int64() + if err != nil { + return nil, err + } + b.Boundaries = int32(boundaries) + if !iter.ReadArray() { + return nil, errors.New("HistogramBucket must be [boundaries, lower, upper, count]") + } + f, err := strconv.ParseFloat(iter.ReadString(), 64) + if err != nil { + return nil, err + } + b.Lower = model.FloatString(f) + if !iter.ReadArray() { + return nil, errors.New("HistogramBucket must be [boundaries, lower, upper, count]") + } + f, err = strconv.ParseFloat(iter.ReadString(), 64) + if err != nil { + return nil, err + } + b.Upper = model.FloatString(f) + if !iter.ReadArray() { + return nil, errors.New("HistogramBucket must be [boundaries, lower, upper, count]") + } + f, err = strconv.ParseFloat(iter.ReadString(), 64) + if err != nil { + return nil, err + } + b.Count = model.FloatString(f) + if iter.ReadArray() { + return nil, errors.New("HistogramBucket has too many values, must be [boundaries, lower, upper, count]") + } + return &b, nil +} + +// marshalHistogramBucket writes something like: [ 3, "-0.25", "0.25", "3"] +// See marshalHistogram to understand what the numbers mean +func marshalHistogramBucket(b model.HistogramBucket, stream *json.Stream) { + stream.WriteArrayStart() + stream.WriteInt32(b.Boundaries) + stream.WriteMore() + marshalFloat(float64(b.Lower), stream) + stream.WriteMore() + marshalFloat(float64(b.Upper), stream) + stream.WriteMore() + marshalFloat(float64(b.Count), stream) + stream.WriteArrayEnd() +} + +// marshalHistogram writes something like: +// +// { +// "count": "42", +// "sum": "34593.34", +// "buckets": [ +// [ 3, "-0.25", "0.25", "3"], +// [ 0, "0.25", "0.5", "12"], +// [ 0, "0.5", "1", "21"], +// [ 0, "2", "4", "6"] +// ] +// } +// +// The 1st element in each bucket array determines if the boundaries are +// inclusive (AKA closed) or exclusive (AKA open): +// +// 0: lower exclusive, upper inclusive +// 1: lower inclusive, upper exclusive +// 2: both exclusive +// 3: both inclusive +// +// The 2nd and 3rd elements are the lower and upper boundary. The 4th element is +// the bucket count. +func marshalHistogram(h model.SampleHistogram, stream *json.Stream) { + stream.WriteObjectStart() + stream.WriteObjectField(`count`) + marshalFloat(float64(h.Count), stream) + stream.WriteMore() + stream.WriteObjectField(`sum`) + marshalFloat(float64(h.Sum), stream) + + bucketFound := false + for _, bucket := range h.Buckets { + if bucket.Count == 0 { + continue // No need to expose empty buckets in JSON. + } + stream.WriteMore() + if !bucketFound { + stream.WriteObjectField(`buckets`) + stream.WriteArrayStart() + } + bucketFound = true + marshalHistogramBucket(*bucket, stream) + } + if bucketFound { + stream.WriteArrayEnd() + } + stream.WriteObjectEnd() +} + +func marshalJSONIsEmpty(ptr unsafe.Pointer) bool { + return false +} + +const ( + apiPrefix = "/api/v1" + + epAlerts = apiPrefix + "/alerts" + epAlertManagers = apiPrefix + "/alertmanagers" + epQuery = apiPrefix + "/query" + epQueryRange = apiPrefix + "/query_range" + epQueryExemplars = apiPrefix + "/query_exemplars" + epLabels = apiPrefix + "/labels" + epLabelValues = apiPrefix + "/label/:name/values" + epSeries = apiPrefix + "/series" + epTargets = apiPrefix + "/targets" + epTargetsMetadata = apiPrefix + "/targets/metadata" + epMetadata = apiPrefix + "/metadata" + epRules = apiPrefix + "/rules" + epSnapshot = apiPrefix + "/admin/tsdb/snapshot" + epDeleteSeries = apiPrefix + "/admin/tsdb/delete_series" + epCleanTombstones = apiPrefix + "/admin/tsdb/clean_tombstones" + epConfig = apiPrefix + "/status/config" + epFlags = apiPrefix + "/status/flags" + epBuildinfo = apiPrefix + "/status/buildinfo" + epRuntimeinfo = apiPrefix + "/status/runtimeinfo" + epTSDB = apiPrefix + "/status/tsdb" + epWalReplay = apiPrefix + "/status/walreplay" +) + +// AlertState models the state of an alert. +type AlertState string + +// ErrorType models the different API error types. +type ErrorType string + +// HealthStatus models the health status of a scrape target. +type HealthStatus string + +// RuleType models the type of a rule. +type RuleType string + +// RuleHealth models the health status of a rule. +type RuleHealth string + +// MetricType models the type of a metric. +type MetricType string + +const ( + // Possible values for AlertState. + AlertStateFiring AlertState = "firing" + AlertStateInactive AlertState = "inactive" + AlertStatePending AlertState = "pending" + + // Possible values for ErrorType. + ErrBadData ErrorType = "bad_data" + ErrTimeout ErrorType = "timeout" + ErrCanceled ErrorType = "canceled" + ErrExec ErrorType = "execution" + ErrBadResponse ErrorType = "bad_response" + ErrServer ErrorType = "server_error" + ErrClient ErrorType = "client_error" + + // Possible values for HealthStatus. + HealthGood HealthStatus = "up" + HealthUnknown HealthStatus = "unknown" + HealthBad HealthStatus = "down" + + // Possible values for RuleType. + RuleTypeRecording RuleType = "recording" + RuleTypeAlerting RuleType = "alerting" + + // Possible values for RuleHealth. + RuleHealthGood = "ok" + RuleHealthUnknown = "unknown" + RuleHealthBad = "err" + + // Possible values for MetricType + MetricTypeCounter MetricType = "counter" + MetricTypeGauge MetricType = "gauge" + MetricTypeHistogram MetricType = "histogram" + MetricTypeGaugeHistogram MetricType = "gaugehistogram" + MetricTypeSummary MetricType = "summary" + MetricTypeInfo MetricType = "info" + MetricTypeStateset MetricType = "stateset" + MetricTypeUnknown MetricType = "unknown" +) + +// Error is an error returned by the API. +type Error struct { + Type ErrorType + Msg string + Detail string +} + +func (e *Error) Error() string { + return fmt.Sprintf("%s: %s", e.Type, e.Msg) +} + +// Range represents a sliced time range. +type Range struct { + // The boundaries of the time range. + Start, End time.Time + // The maximum time between two slices within the boundaries. + Step time.Duration +} + +// API provides bindings for Prometheus's v1 API. +type API interface { + // Alerts returns a list of all active alerts. + Alerts(ctx context.Context) (AlertsResult, error) + // AlertManagers returns an overview of the current state of the Prometheus alert manager discovery. + AlertManagers(ctx context.Context) (AlertManagersResult, error) + // CleanTombstones removes the deleted data from disk and cleans up the existing tombstones. + CleanTombstones(ctx context.Context) error + // Config returns the current Prometheus configuration. + Config(ctx context.Context) (ConfigResult, error) + // DeleteSeries deletes data for a selection of series in a time range. + DeleteSeries(ctx context.Context, matches []string, startTime, endTime time.Time) error + // Flags returns the flag values that Prometheus was launched with. + Flags(ctx context.Context) (FlagsResult, error) + // LabelNames returns the unique label names present in the block in sorted order by given time range and matchers. + LabelNames(ctx context.Context, matches []string, startTime, endTime time.Time, opts ...Option) ([]string, Warnings, error) + // LabelValues performs a query for the values of the given label, time range and matchers. + LabelValues(ctx context.Context, label string, matches []string, startTime, endTime time.Time, opts ...Option) (model.LabelValues, Warnings, error) + // Query performs a query for the given time. + Query(ctx context.Context, query string, ts time.Time, opts ...Option) (model.Value, Warnings, error) + // QueryRange performs a query for the given range. + QueryRange(ctx context.Context, query string, r Range, opts ...Option) (model.Value, Warnings, error) + // QueryExemplars performs a query for exemplars by the given query and time range. + QueryExemplars(ctx context.Context, query string, startTime, endTime time.Time) ([]ExemplarQueryResult, error) + // Buildinfo returns various build information properties about the Prometheus server + Buildinfo(ctx context.Context) (BuildinfoResult, error) + // Runtimeinfo returns the various runtime information properties about the Prometheus server. + Runtimeinfo(ctx context.Context) (RuntimeinfoResult, error) + // Series finds series by label matchers. + Series(ctx context.Context, matches []string, startTime, endTime time.Time, opts ...Option) ([]model.LabelSet, Warnings, error) + // Snapshot creates a snapshot of all current data into snapshots/- + // under the TSDB's data directory and returns the directory as response. + Snapshot(ctx context.Context, skipHead bool) (SnapshotResult, error) + // Rules returns a list of alerting and recording rules that are currently loaded. + Rules(ctx context.Context) (RulesResult, error) + // Targets returns an overview of the current state of the Prometheus target discovery. + Targets(ctx context.Context) (TargetsResult, error) + // TargetsMetadata returns metadata about metrics currently scraped by the target. + TargetsMetadata(ctx context.Context, matchTarget, metric, limit string) ([]MetricMetadata, error) + // Metadata returns metadata about metrics currently scraped by the metric name. + Metadata(ctx context.Context, metric, limit string) (map[string][]Metadata, error) + // TSDB returns the cardinality statistics. + TSDB(ctx context.Context, opts ...Option) (TSDBResult, error) + // WalReplay returns the current replay status of the wal. + WalReplay(ctx context.Context) (WalReplayStatus, error) +} + +// AlertsResult contains the result from querying the alerts endpoint. +type AlertsResult struct { + Alerts []Alert `json:"alerts"` +} + +// AlertManagersResult contains the result from querying the alertmanagers endpoint. +type AlertManagersResult struct { + Active []AlertManager `json:"activeAlertManagers"` + Dropped []AlertManager `json:"droppedAlertManagers"` +} + +// AlertManager models a configured Alert Manager. +type AlertManager struct { + URL string `json:"url"` +} + +// ConfigResult contains the result from querying the config endpoint. +type ConfigResult struct { + YAML string `json:"yaml"` +} + +// FlagsResult contains the result from querying the flag endpoint. +type FlagsResult map[string]string + +// BuildinfoResult contains the results from querying the buildinfo endpoint. +type BuildinfoResult struct { + Version string `json:"version"` + Revision string `json:"revision"` + Branch string `json:"branch"` + BuildUser string `json:"buildUser"` + BuildDate string `json:"buildDate"` + GoVersion string `json:"goVersion"` +} + +// RuntimeinfoResult contains the result from querying the runtimeinfo endpoint. +type RuntimeinfoResult struct { + StartTime time.Time `json:"startTime"` + CWD string `json:"CWD"` + ReloadConfigSuccess bool `json:"reloadConfigSuccess"` + LastConfigTime time.Time `json:"lastConfigTime"` + CorruptionCount int `json:"corruptionCount"` + GoroutineCount int `json:"goroutineCount"` + GOMAXPROCS int `json:"GOMAXPROCS"` + GOGC string `json:"GOGC"` + GODEBUG string `json:"GODEBUG"` + StorageRetention string `json:"storageRetention"` +} + +// SnapshotResult contains the result from querying the snapshot endpoint. +type SnapshotResult struct { + Name string `json:"name"` +} + +// RulesResult contains the result from querying the rules endpoint. +type RulesResult struct { + Groups []RuleGroup `json:"groups"` +} + +// RuleGroup models a rule group that contains a set of recording and alerting rules. +type RuleGroup struct { + Name string `json:"name"` + File string `json:"file"` + Interval float64 `json:"interval"` + Rules Rules `json:"rules"` +} + +// Recording and alerting rules are stored in the same slice to preserve the order +// that rules are returned in by the API. +// +// Rule types can be determined using a type switch: +// +// switch v := rule.(type) { +// case RecordingRule: +// fmt.Print("got a recording rule") +// case AlertingRule: +// fmt.Print("got a alerting rule") +// default: +// fmt.Printf("unknown rule type %s", v) +// } +type Rules []interface{} + +// AlertingRule models a alerting rule. +type AlertingRule struct { + Name string `json:"name"` + Query string `json:"query"` + Duration float64 `json:"duration"` + Labels model.LabelSet `json:"labels"` + Annotations model.LabelSet `json:"annotations"` + Alerts []*Alert `json:"alerts"` + Health RuleHealth `json:"health"` + LastError string `json:"lastError,omitempty"` + EvaluationTime float64 `json:"evaluationTime"` + LastEvaluation time.Time `json:"lastEvaluation"` + State string `json:"state"` +} + +// RecordingRule models a recording rule. +type RecordingRule struct { + Name string `json:"name"` + Query string `json:"query"` + Labels model.LabelSet `json:"labels,omitempty"` + Health RuleHealth `json:"health"` + LastError string `json:"lastError,omitempty"` + EvaluationTime float64 `json:"evaluationTime"` + LastEvaluation time.Time `json:"lastEvaluation"` +} + +// Alert models an active alert. +type Alert struct { + ActiveAt time.Time `json:"activeAt"` + Annotations model.LabelSet + Labels model.LabelSet + State AlertState + Value string +} + +// TargetsResult contains the result from querying the targets endpoint. +type TargetsResult struct { + Active []ActiveTarget `json:"activeTargets"` + Dropped []DroppedTarget `json:"droppedTargets"` +} + +// ActiveTarget models an active Prometheus scrape target. +type ActiveTarget struct { + DiscoveredLabels map[string]string `json:"discoveredLabels"` + Labels model.LabelSet `json:"labels"` + ScrapePool string `json:"scrapePool"` + ScrapeURL string `json:"scrapeUrl"` + GlobalURL string `json:"globalUrl"` + LastError string `json:"lastError"` + LastScrape time.Time `json:"lastScrape"` + LastScrapeDuration float64 `json:"lastScrapeDuration"` + Health HealthStatus `json:"health"` +} + +// DroppedTarget models a dropped Prometheus scrape target. +type DroppedTarget struct { + DiscoveredLabels map[string]string `json:"discoveredLabels"` +} + +// MetricMetadata models the metadata of a metric with its scrape target and name. +type MetricMetadata struct { + Target map[string]string `json:"target"` + Metric string `json:"metric,omitempty"` + Type MetricType `json:"type"` + Help string `json:"help"` + Unit string `json:"unit"` +} + +// Metadata models the metadata of a metric. +type Metadata struct { + Type MetricType `json:"type"` + Help string `json:"help"` + Unit string `json:"unit"` +} + +// queryResult contains result data for a query. +type queryResult struct { + Type model.ValueType `json:"resultType"` + Result interface{} `json:"result"` + + // The decoded value. + v model.Value +} + +// TSDBResult contains the result from querying the tsdb endpoint. +type TSDBResult struct { + HeadStats TSDBHeadStats `json:"headStats"` + SeriesCountByMetricName []Stat `json:"seriesCountByMetricName"` + LabelValueCountByLabelName []Stat `json:"labelValueCountByLabelName"` + MemoryInBytesByLabelName []Stat `json:"memoryInBytesByLabelName"` + SeriesCountByLabelValuePair []Stat `json:"seriesCountByLabelValuePair"` +} + +// TSDBHeadStats contains TSDB stats +type TSDBHeadStats struct { + NumSeries int `json:"numSeries"` + NumLabelPairs int `json:"numLabelPairs"` + ChunkCount int `json:"chunkCount"` + MinTime int `json:"minTime"` + MaxTime int `json:"maxTime"` +} + +// WalReplayStatus represents the wal replay status. +type WalReplayStatus struct { + Min int `json:"min"` + Max int `json:"max"` + Current int `json:"current"` +} + +// Stat models information about statistic value. +type Stat struct { + Name string `json:"name"` + Value uint64 `json:"value"` +} + +func (rg *RuleGroup) UnmarshalJSON(b []byte) error { + v := struct { + Name string `json:"name"` + File string `json:"file"` + Interval float64 `json:"interval"` + Rules []json.RawMessage `json:"rules"` + }{} + + if err := json.Unmarshal(b, &v); err != nil { + return err + } + + rg.Name = v.Name + rg.File = v.File + rg.Interval = v.Interval + + for _, rule := range v.Rules { + alertingRule := AlertingRule{} + if err := json.Unmarshal(rule, &alertingRule); err == nil { + rg.Rules = append(rg.Rules, alertingRule) + continue + } + recordingRule := RecordingRule{} + if err := json.Unmarshal(rule, &recordingRule); err == nil { + rg.Rules = append(rg.Rules, recordingRule) + continue + } + return errors.New("failed to decode JSON into an alerting or recording rule") + } + + return nil +} + +func (r *AlertingRule) UnmarshalJSON(b []byte) error { + v := struct { + Type string `json:"type"` + }{} + if err := json.Unmarshal(b, &v); err != nil { + return err + } + if v.Type == "" { + return errors.New("type field not present in rule") + } + if v.Type != string(RuleTypeAlerting) { + return fmt.Errorf("expected rule of type %s but got %s", string(RuleTypeAlerting), v.Type) + } + + rule := struct { + Name string `json:"name"` + Query string `json:"query"` + Duration float64 `json:"duration"` + Labels model.LabelSet `json:"labels"` + Annotations model.LabelSet `json:"annotations"` + Alerts []*Alert `json:"alerts"` + Health RuleHealth `json:"health"` + LastError string `json:"lastError,omitempty"` + EvaluationTime float64 `json:"evaluationTime"` + LastEvaluation time.Time `json:"lastEvaluation"` + State string `json:"state"` + }{} + if err := json.Unmarshal(b, &rule); err != nil { + return err + } + r.Health = rule.Health + r.Annotations = rule.Annotations + r.Name = rule.Name + r.Query = rule.Query + r.Alerts = rule.Alerts + r.Duration = rule.Duration + r.Labels = rule.Labels + r.LastError = rule.LastError + r.EvaluationTime = rule.EvaluationTime + r.LastEvaluation = rule.LastEvaluation + r.State = rule.State + + return nil +} + +func (r *RecordingRule) UnmarshalJSON(b []byte) error { + v := struct { + Type string `json:"type"` + }{} + if err := json.Unmarshal(b, &v); err != nil { + return err + } + if v.Type == "" { + return errors.New("type field not present in rule") + } + if v.Type != string(RuleTypeRecording) { + return fmt.Errorf("expected rule of type %s but got %s", string(RuleTypeRecording), v.Type) + } + + rule := struct { + Name string `json:"name"` + Query string `json:"query"` + Labels model.LabelSet `json:"labels,omitempty"` + Health RuleHealth `json:"health"` + LastError string `json:"lastError,omitempty"` + EvaluationTime float64 `json:"evaluationTime"` + LastEvaluation time.Time `json:"lastEvaluation"` + }{} + if err := json.Unmarshal(b, &rule); err != nil { + return err + } + r.Health = rule.Health + r.Labels = rule.Labels + r.Name = rule.Name + r.LastError = rule.LastError + r.Query = rule.Query + r.EvaluationTime = rule.EvaluationTime + r.LastEvaluation = rule.LastEvaluation + + return nil +} + +func (qr *queryResult) UnmarshalJSON(b []byte) error { + v := struct { + Type model.ValueType `json:"resultType"` + Result json.RawMessage `json:"result"` + }{} + + err := json.Unmarshal(b, &v) + if err != nil { + return err + } + + switch v.Type { + case model.ValScalar: + var sv model.Scalar + err = json.Unmarshal(v.Result, &sv) + qr.v = &sv + + case model.ValVector: + var vv model.Vector + err = json.Unmarshal(v.Result, &vv) + qr.v = vv + + case model.ValMatrix: + var mv model.Matrix + err = json.Unmarshal(v.Result, &mv) + qr.v = mv + + default: + err = fmt.Errorf("unexpected value type %q", v.Type) + } + return err +} + +// Exemplar is additional information associated with a time series. +type Exemplar struct { + Labels model.LabelSet `json:"labels"` + Value model.SampleValue `json:"value"` + Timestamp model.Time `json:"timestamp"` +} + +type ExemplarQueryResult struct { + SeriesLabels model.LabelSet `json:"seriesLabels"` + Exemplars []Exemplar `json:"exemplars"` +} + +// NewAPI returns a new API for the client. +// +// It is safe to use the returned API from multiple goroutines. +func NewAPI(c api.Client) API { + return &httpAPI{ + client: &apiClientImpl{ + client: c, + }, + } +} + +type httpAPI struct { + client apiClient +} + +func (h *httpAPI) Alerts(ctx context.Context) (AlertsResult, error) { + u := h.client.URL(epAlerts, nil) + + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + if err != nil { + return AlertsResult{}, err + } + + _, body, _, err := h.client.Do(ctx, req) + if err != nil { + return AlertsResult{}, err + } + + var res AlertsResult + err = json.Unmarshal(body, &res) + return res, err +} + +func (h *httpAPI) AlertManagers(ctx context.Context) (AlertManagersResult, error) { + u := h.client.URL(epAlertManagers, nil) + + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + if err != nil { + return AlertManagersResult{}, err + } + + _, body, _, err := h.client.Do(ctx, req) + if err != nil { + return AlertManagersResult{}, err + } + + var res AlertManagersResult + err = json.Unmarshal(body, &res) + return res, err +} + +func (h *httpAPI) CleanTombstones(ctx context.Context) error { + u := h.client.URL(epCleanTombstones, nil) + + req, err := http.NewRequest(http.MethodPost, u.String(), nil) + if err != nil { + return err + } + + _, _, _, err = h.client.Do(ctx, req) + return err +} + +func (h *httpAPI) Config(ctx context.Context) (ConfigResult, error) { + u := h.client.URL(epConfig, nil) + + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + if err != nil { + return ConfigResult{}, err + } + + _, body, _, err := h.client.Do(ctx, req) + if err != nil { + return ConfigResult{}, err + } + + var res ConfigResult + err = json.Unmarshal(body, &res) + return res, err +} + +func (h *httpAPI) DeleteSeries(ctx context.Context, matches []string, startTime, endTime time.Time) error { + u := h.client.URL(epDeleteSeries, nil) + q := u.Query() + + for _, m := range matches { + q.Add("match[]", m) + } + + if !startTime.IsZero() { + q.Set("start", formatTime(startTime)) + } + if !endTime.IsZero() { + q.Set("end", formatTime(endTime)) + } + + u.RawQuery = q.Encode() + + req, err := http.NewRequest(http.MethodPost, u.String(), nil) + if err != nil { + return err + } + + _, _, _, err = h.client.Do(ctx, req) + return err +} + +func (h *httpAPI) Flags(ctx context.Context) (FlagsResult, error) { + u := h.client.URL(epFlags, nil) + + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + if err != nil { + return FlagsResult{}, err + } + + _, body, _, err := h.client.Do(ctx, req) + if err != nil { + return FlagsResult{}, err + } + + var res FlagsResult + err = json.Unmarshal(body, &res) + return res, err +} + +func (h *httpAPI) Buildinfo(ctx context.Context) (BuildinfoResult, error) { + u := h.client.URL(epBuildinfo, nil) + + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + if err != nil { + return BuildinfoResult{}, err + } + + _, body, _, err := h.client.Do(ctx, req) + if err != nil { + return BuildinfoResult{}, err + } + + var res BuildinfoResult + err = json.Unmarshal(body, &res) + return res, err +} + +func (h *httpAPI) Runtimeinfo(ctx context.Context) (RuntimeinfoResult, error) { + u := h.client.URL(epRuntimeinfo, nil) + + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + if err != nil { + return RuntimeinfoResult{}, err + } + + _, body, _, err := h.client.Do(ctx, req) + if err != nil { + return RuntimeinfoResult{}, err + } + + var res RuntimeinfoResult + err = json.Unmarshal(body, &res) + return res, err +} + +func (h *httpAPI) LabelNames(ctx context.Context, matches []string, startTime, endTime time.Time, opts ...Option) ([]string, Warnings, error) { + u := h.client.URL(epLabels, nil) + q := addOptionalURLParams(u.Query(), opts) + + if !startTime.IsZero() { + q.Set("start", formatTime(startTime)) + } + if !endTime.IsZero() { + q.Set("end", formatTime(endTime)) + } + for _, m := range matches { + q.Add("match[]", m) + } + + _, body, w, err := h.client.DoGetFallback(ctx, u, q) + if err != nil { + return nil, w, err + } + var labelNames []string + err = json.Unmarshal(body, &labelNames) + return labelNames, w, err +} + +func (h *httpAPI) LabelValues(ctx context.Context, label string, matches []string, startTime, endTime time.Time, opts ...Option) (model.LabelValues, Warnings, error) { + u := h.client.URL(epLabelValues, map[string]string{"name": label}) + q := addOptionalURLParams(u.Query(), opts) + + if !startTime.IsZero() { + q.Set("start", formatTime(startTime)) + } + if !endTime.IsZero() { + q.Set("end", formatTime(endTime)) + } + for _, m := range matches { + q.Add("match[]", m) + } + + u.RawQuery = q.Encode() + + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + if err != nil { + return nil, nil, err + } + _, body, w, err := h.client.Do(ctx, req) + if err != nil { + return nil, w, err + } + var labelValues model.LabelValues + err = json.Unmarshal(body, &labelValues) + return labelValues, w, err +} + +// StatsValue is a type for `stats` query parameter. +type StatsValue string + +// AllStatsValue is the query parameter value to return all the query statistics. +const ( + AllStatsValue StatsValue = "all" +) + +type apiOptions struct { + timeout time.Duration + lookbackDelta time.Duration + stats StatsValue + limit uint64 +} + +type Option func(c *apiOptions) + +// WithTimeout can be used to provide an optional query evaluation timeout for Query and QueryRange. +// https://prometheus.io/docs/prometheus/latest/querying/api/#instant-queries +func WithTimeout(timeout time.Duration) Option { + return func(o *apiOptions) { + o.timeout = timeout + } +} + +// WithLookbackDelta can be used to provide an optional query lookback delta for Query and QueryRange. +// This URL variable is not documented on Prometheus HTTP API. +// https://github.com/prometheus/prometheus/blob/e04913aea2792a5c8bc7b3130c389ca1b027dd9b/promql/engine.go#L162-L167 +func WithLookbackDelta(lookbackDelta time.Duration) Option { + return func(o *apiOptions) { + o.lookbackDelta = lookbackDelta + } +} + +// WithStats can be used to provide an optional per step stats for Query and QueryRange. +// This URL variable is not documented on Prometheus HTTP API. +// https://github.com/prometheus/prometheus/blob/e04913aea2792a5c8bc7b3130c389ca1b027dd9b/promql/engine.go#L162-L167 +func WithStats(stats StatsValue) Option { + return func(o *apiOptions) { + o.stats = stats + } +} + +// WithLimit provides an optional maximum number of returned entries for APIs that support limit parameter +// e.g. https://prometheus.io/docs/prometheus/latest/querying/api/#instant-querie:~:text=%3A%20End%20timestamp.-,limit%3D%3Cnumber%3E,-%3A%20Maximum%20number%20of +func WithLimit(limit uint64) Option { + return func(o *apiOptions) { + o.limit = limit + } +} + +func addOptionalURLParams(q url.Values, opts []Option) url.Values { + opt := &apiOptions{} + for _, o := range opts { + o(opt) + } + + if opt.timeout > 0 { + q.Set("timeout", opt.timeout.String()) + } + + if opt.lookbackDelta > 0 { + q.Set("lookback_delta", opt.lookbackDelta.String()) + } + + if opt.stats != "" { + q.Set("stats", string(opt.stats)) + } + + if opt.limit > 0 { + q.Set("limit", strconv.FormatUint(opt.limit, 10)) + } + + return q +} + +func (h *httpAPI) Query(ctx context.Context, query string, ts time.Time, opts ...Option) (model.Value, Warnings, error) { + u := h.client.URL(epQuery, nil) + q := addOptionalURLParams(u.Query(), opts) + + q.Set("query", query) + if !ts.IsZero() { + q.Set("time", formatTime(ts)) + } + + _, body, warnings, err := h.client.DoGetFallback(ctx, u, q) + if err != nil { + return nil, warnings, err + } + + var qres queryResult + return qres.v, warnings, json.Unmarshal(body, &qres) +} + +func (h *httpAPI) QueryRange(ctx context.Context, query string, r Range, opts ...Option) (model.Value, Warnings, error) { + u := h.client.URL(epQueryRange, nil) + q := addOptionalURLParams(u.Query(), opts) + + q.Set("query", query) + q.Set("start", formatTime(r.Start)) + q.Set("end", formatTime(r.End)) + q.Set("step", strconv.FormatFloat(r.Step.Seconds(), 'f', -1, 64)) + + _, body, warnings, err := h.client.DoGetFallback(ctx, u, q) + if err != nil { + return nil, warnings, err + } + + var qres queryResult + return qres.v, warnings, json.Unmarshal(body, &qres) +} + +func (h *httpAPI) Series(ctx context.Context, matches []string, startTime, endTime time.Time, opts ...Option) ([]model.LabelSet, Warnings, error) { + u := h.client.URL(epSeries, nil) + q := addOptionalURLParams(u.Query(), opts) + + for _, m := range matches { + q.Add("match[]", m) + } + + if !startTime.IsZero() { + q.Set("start", formatTime(startTime)) + } + if !endTime.IsZero() { + q.Set("end", formatTime(endTime)) + } + + _, body, warnings, err := h.client.DoGetFallback(ctx, u, q) + if err != nil { + return nil, warnings, err + } + + var mset []model.LabelSet + return mset, warnings, json.Unmarshal(body, &mset) +} + +func (h *httpAPI) Snapshot(ctx context.Context, skipHead bool) (SnapshotResult, error) { + u := h.client.URL(epSnapshot, nil) + q := u.Query() + + q.Set("skip_head", strconv.FormatBool(skipHead)) + + u.RawQuery = q.Encode() + + req, err := http.NewRequest(http.MethodPost, u.String(), nil) + if err != nil { + return SnapshotResult{}, err + } + + _, body, _, err := h.client.Do(ctx, req) + if err != nil { + return SnapshotResult{}, err + } + + var res SnapshotResult + err = json.Unmarshal(body, &res) + return res, err +} + +func (h *httpAPI) Rules(ctx context.Context) (RulesResult, error) { + u := h.client.URL(epRules, nil) + + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + if err != nil { + return RulesResult{}, err + } + + _, body, _, err := h.client.Do(ctx, req) + if err != nil { + return RulesResult{}, err + } + + var res RulesResult + err = json.Unmarshal(body, &res) + return res, err +} + +func (h *httpAPI) Targets(ctx context.Context) (TargetsResult, error) { + u := h.client.URL(epTargets, nil) + + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + if err != nil { + return TargetsResult{}, err + } + + _, body, _, err := h.client.Do(ctx, req) + if err != nil { + return TargetsResult{}, err + } + + var res TargetsResult + err = json.Unmarshal(body, &res) + return res, err +} + +func (h *httpAPI) TargetsMetadata(ctx context.Context, matchTarget, metric, limit string) ([]MetricMetadata, error) { + u := h.client.URL(epTargetsMetadata, nil) + q := u.Query() + + q.Set("match_target", matchTarget) + q.Set("metric", metric) + q.Set("limit", limit) + + u.RawQuery = q.Encode() + + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + if err != nil { + return nil, err + } + + _, body, _, err := h.client.Do(ctx, req) + if err != nil { + return nil, err + } + + var res []MetricMetadata + err = json.Unmarshal(body, &res) + return res, err +} + +func (h *httpAPI) Metadata(ctx context.Context, metric, limit string) (map[string][]Metadata, error) { + u := h.client.URL(epMetadata, nil) + q := u.Query() + + q.Set("metric", metric) + q.Set("limit", limit) + + u.RawQuery = q.Encode() + + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + if err != nil { + return nil, err + } + + _, body, _, err := h.client.Do(ctx, req) + if err != nil { + return nil, err + } + + var res map[string][]Metadata + err = json.Unmarshal(body, &res) + return res, err +} + +func (h *httpAPI) TSDB(ctx context.Context, opts ...Option) (TSDBResult, error) { + u := h.client.URL(epTSDB, nil) + q := addOptionalURLParams(u.Query(), opts) + u.RawQuery = q.Encode() + + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + if err != nil { + return TSDBResult{}, err + } + + _, body, _, err := h.client.Do(ctx, req) + if err != nil { + return TSDBResult{}, err + } + + var res TSDBResult + err = json.Unmarshal(body, &res) + return res, err +} + +func (h *httpAPI) WalReplay(ctx context.Context) (WalReplayStatus, error) { + u := h.client.URL(epWalReplay, nil) + + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + if err != nil { + return WalReplayStatus{}, err + } + + _, body, _, err := h.client.Do(ctx, req) + if err != nil { + return WalReplayStatus{}, err + } + + var res WalReplayStatus + err = json.Unmarshal(body, &res) + return res, err +} + +func (h *httpAPI) QueryExemplars(ctx context.Context, query string, startTime, endTime time.Time) ([]ExemplarQueryResult, error) { + u := h.client.URL(epQueryExemplars, nil) + q := u.Query() + + q.Set("query", query) + if !startTime.IsZero() { + q.Set("start", formatTime(startTime)) + } + if !endTime.IsZero() { + q.Set("end", formatTime(endTime)) + } + + _, body, _, err := h.client.DoGetFallback(ctx, u, q) + if err != nil { + return nil, err + } + + var res []ExemplarQueryResult + err = json.Unmarshal(body, &res) + return res, err +} + +// Warnings is an array of non critical errors +type Warnings []string + +// apiClient wraps a regular client and processes successful API responses. +// Successful also includes responses that errored at the API level. +type apiClient interface { + URL(ep string, args map[string]string) *url.URL + Do(context.Context, *http.Request) (*http.Response, []byte, Warnings, error) + DoGetFallback(ctx context.Context, u *url.URL, args url.Values) (*http.Response, []byte, Warnings, error) +} + +type apiClientImpl struct { + client api.Client +} + +type apiResponse struct { + Status string `json:"status"` + Data json.RawMessage `json:"data"` + ErrorType ErrorType `json:"errorType"` + Error string `json:"error"` + Warnings []string `json:"warnings,omitempty"` +} + +func apiError(code int) bool { + // These are the codes that Prometheus sends when it returns an error. + return code == http.StatusUnprocessableEntity || code == http.StatusBadRequest +} + +func errorTypeAndMsgFor(resp *http.Response) (ErrorType, string) { + switch resp.StatusCode / 100 { + case 4: + return ErrClient, fmt.Sprintf("client error: %d", resp.StatusCode) + case 5: + return ErrServer, fmt.Sprintf("server error: %d", resp.StatusCode) + } + return ErrBadResponse, fmt.Sprintf("bad response code %d", resp.StatusCode) +} + +func (h *apiClientImpl) URL(ep string, args map[string]string) *url.URL { + return h.client.URL(ep, args) +} + +func (h *apiClientImpl) Do(ctx context.Context, req *http.Request) (*http.Response, []byte, Warnings, error) { + resp, body, err := h.client.Do(ctx, req) + if err != nil { + return resp, body, nil, err + } + + code := resp.StatusCode + + if code/100 != 2 && !apiError(code) { + errorType, errorMsg := errorTypeAndMsgFor(resp) + return resp, body, nil, &Error{ + Type: errorType, + Msg: errorMsg, + Detail: string(body), + } + } + + var result apiResponse + + if http.StatusNoContent != code { + if jsonErr := json.Unmarshal(body, &result); jsonErr != nil { + return resp, body, nil, &Error{ + Type: ErrBadResponse, + Msg: jsonErr.Error(), + } + } + } + + if apiError(code) && result.Status == "success" { + err = &Error{ + Type: ErrBadResponse, + Msg: "inconsistent body for response code", + } + } + + if result.Status == "error" { + err = &Error{ + Type: result.ErrorType, + Msg: result.Error, + } + } + + return resp, []byte(result.Data), result.Warnings, err +} + +// DoGetFallback will attempt to do the request as-is, and on a 405 or 501 it +// will fallback to a GET request. +func (h *apiClientImpl) DoGetFallback(ctx context.Context, u *url.URL, args url.Values) (*http.Response, []byte, Warnings, error) { + encodedArgs := args.Encode() + req, err := http.NewRequest(http.MethodPost, u.String(), strings.NewReader(encodedArgs)) + if err != nil { + return nil, nil, nil, err + } + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + // Following comment originates from https://pkg.go.dev/net/http#Transport + // Transport only retries a request upon encountering a network error if the request is + // idempotent and either has no body or has its Request.GetBody defined. HTTP requests + // are considered idempotent if they have HTTP methods GET, HEAD, OPTIONS, or TRACE; or + // if their Header map contains an "Idempotency-Key" or "X-Idempotency-Key" entry. If the + // idempotency key value is a zero-length slice, the request is treated as idempotent but + // the header is not sent on the wire. + req.Header["Idempotency-Key"] = nil + + resp, body, warnings, err := h.Do(ctx, req) + if resp != nil && (resp.StatusCode == http.StatusMethodNotAllowed || resp.StatusCode == http.StatusNotImplemented) { + u.RawQuery = encodedArgs + req, err = http.NewRequest(http.MethodGet, u.String(), nil) + if err != nil { + return nil, nil, warnings, err + } + return h.Do(ctx, req) + } + return resp, body, warnings, err +} + +func formatTime(t time.Time) string { + return strconv.FormatFloat(float64(t.Unix())+float64(t.Nanosecond())/1e9, 'f', -1, 64) +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/internal/difflib.go b/vendor/github.com/prometheus/client_golang/prometheus/internal/difflib.go index 8b016355a..7bac0da33 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/internal/difflib.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/internal/difflib.go @@ -453,7 +453,7 @@ func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode { } group = append(group, OpCode{c.Tag, i1, i2, j1, j2}) } - if len(group) > 0 && !(len(group) == 1 && group[0].Tag == 'e') { + if len(group) > 0 && (len(group) != 1 || group[0].Tag != 'e') { groups = append(groups, group) } return groups @@ -568,7 +568,7 @@ func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error { buf := bufio.NewWriter(writer) defer buf.Flush() wf := func(format string, args ...interface{}) error { - _, err := buf.WriteString(fmt.Sprintf(format, args...)) + _, err := fmt.Fprintf(buf, format, args...) return err } ws := func(s string) error { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/metric.go b/vendor/github.com/prometheus/client_golang/prometheus/metric.go index 592eec3e2..76e59f128 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/metric.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/metric.go @@ -186,21 +186,31 @@ func (m *withExemplarsMetric) Write(pb *dto.Metric) error { case pb.Counter != nil: pb.Counter.Exemplar = m.exemplars[len(m.exemplars)-1] case pb.Histogram != nil: + h := pb.Histogram for _, e := range m.exemplars { - // pb.Histogram.Bucket are sorted by UpperBound. - i := sort.Search(len(pb.Histogram.Bucket), func(i int) bool { - return pb.Histogram.Bucket[i].GetUpperBound() >= e.GetValue() + if (h.GetZeroThreshold() != 0 || h.GetZeroCount() != 0 || + len(h.PositiveSpan) != 0 || len(h.NegativeSpan) != 0) && + e.GetTimestamp() != nil { + h.Exemplars = append(h.Exemplars, e) + if len(h.Bucket) == 0 { + // Don't proceed to classic buckets if there are none. + continue + } + } + // h.Bucket are sorted by UpperBound. + i := sort.Search(len(h.Bucket), func(i int) bool { + return h.Bucket[i].GetUpperBound() >= e.GetValue() }) - if i < len(pb.Histogram.Bucket) { - pb.Histogram.Bucket[i].Exemplar = e + if i < len(h.Bucket) { + h.Bucket[i].Exemplar = e } else { // The +Inf bucket should be explicitly added if there is an exemplar for it, similar to non-const histogram logic in https://github.com/prometheus/client_golang/blob/main/prometheus/histogram.go#L357-L365. b := &dto.Bucket{ - CumulativeCount: proto.Uint64(pb.Histogram.GetSampleCount()), + CumulativeCount: proto.Uint64(h.GetSampleCount()), UpperBound: proto.Float64(math.Inf(1)), Exemplar: e, } - pb.Histogram.Bucket = append(pb.Histogram.Bucket, b) + h.Bucket = append(h.Bucket, b) } } default: @@ -227,6 +237,7 @@ type Exemplar struct { // Only last applicable exemplar is injected from the list. // For example for Counter it means last exemplar is injected. // For Histogram, it means last applicable exemplar for each bucket is injected. +// For a Native Histogram, all valid exemplars are injected. // // NewMetricWithExemplars works best with MustNewConstMetric and // MustNewConstHistogram, see example. diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_darwin.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_darwin.go index 0a61b9846..b32c95fa3 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_darwin.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_darwin.go @@ -25,9 +25,9 @@ import ( "golang.org/x/sys/unix" ) -// notImplementedErr is returned by stub functions that replace cgo functions, when cgo +// errNotImplemented is returned by stub functions that replace cgo functions, when cgo // isn't available. -var notImplementedErr = errors.New("not implemented") +var errNotImplemented = errors.New("not implemented") type memoryInfo struct { vsize uint64 // Virtual memory size in bytes @@ -101,7 +101,7 @@ func (c *processCollector) processCollect(ch chan<- Metric) { if memInfo, err := getMemory(); err == nil { ch <- MustNewConstMetric(c.rss, GaugeValue, float64(memInfo.rss)) ch <- MustNewConstMetric(c.vsize, GaugeValue, float64(memInfo.vsize)) - } else if !errors.Is(err, notImplementedErr) { + } else if !errors.Is(err, errNotImplemented) { // Don't report an error when support is not compiled in. c.reportError(ch, c.rss, err) c.reportError(ch, c.vsize, err) diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_mem_nocgo_darwin.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_mem_nocgo_darwin.go index 8ddb0995d..378865129 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_mem_nocgo_darwin.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_mem_nocgo_darwin.go @@ -16,7 +16,7 @@ package prometheus func getMemory() (*memoryInfo, error) { - return nil, notImplementedErr + return nil, errNotImplemented } // describe returns all descriptions of the collector for Darwin. diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_procfsenabled.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_procfsenabled.go index 9f4b130be..8074f70f5 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_procfsenabled.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_procfsenabled.go @@ -66,11 +66,11 @@ func (c *processCollector) processCollect(ch chan<- Metric) { if netstat, err := p.Netstat(); err == nil { var inOctets, outOctets float64 - if netstat.IpExt.InOctets != nil { - inOctets = *netstat.IpExt.InOctets + if netstat.InOctets != nil { + inOctets = *netstat.InOctets } - if netstat.IpExt.OutOctets != nil { - outOctets = *netstat.IpExt.OutOctets + if netstat.OutOctets != nil { + outOctets = *netstat.OutOctets } ch <- MustNewConstMetric(c.inBytes, CounterValue, inOctets) ch <- MustNewConstMetric(c.outBytes, CounterValue, outOctets) diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go index 356edb786..9332b0249 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go @@ -392,7 +392,7 @@ func isLabelCurried(c prometheus.Collector, label string) bool { func labels(code, method bool, reqMethod string, status int, extraMethods ...string) prometheus.Labels { labels := prometheus.Labels{} - if !(code || method) { + if !code && !method { return labels } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/vec.go b/vendor/github.com/prometheus/client_golang/prometheus/vec.go index 2c808eece..487b46656 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/vec.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/vec.go @@ -79,7 +79,7 @@ func (m *MetricVec) DeleteLabelValues(lvs ...string) bool { return false } - return m.metricMap.deleteByHashWithLabelValues(h, lvs, m.curry) + return m.deleteByHashWithLabelValues(h, lvs, m.curry) } // Delete deletes the metric where the variable labels are the same as those @@ -101,7 +101,7 @@ func (m *MetricVec) Delete(labels Labels) bool { return false } - return m.metricMap.deleteByHashWithLabels(h, labels, m.curry) + return m.deleteByHashWithLabels(h, labels, m.curry) } // DeletePartialMatch deletes all metrics where the variable labels contain all of those @@ -114,7 +114,7 @@ func (m *MetricVec) DeletePartialMatch(labels Labels) int { labels, closer := constrainLabels(m.desc, labels) defer closer() - return m.metricMap.deleteByLabels(labels, m.curry) + return m.deleteByLabels(labels, m.curry) } // Without explicit forwarding of Describe, Collect, Reset, those methods won't @@ -216,7 +216,7 @@ func (m *MetricVec) GetMetricWithLabelValues(lvs ...string) (Metric, error) { return nil, err } - return m.metricMap.getOrCreateMetricWithLabelValues(h, lvs, m.curry), nil + return m.getOrCreateMetricWithLabelValues(h, lvs, m.curry), nil } // GetMetricWith returns the Metric for the given Labels map (the label names @@ -244,7 +244,7 @@ func (m *MetricVec) GetMetricWith(labels Labels) (Metric, error) { return nil, err } - return m.metricMap.getOrCreateMetricWithLabels(h, labels, m.curry), nil + return m.getOrCreateMetricWithLabels(h, labels, m.curry), nil } func (m *MetricVec) hashLabelValues(vals []string) (uint64, error) { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/wrap.go b/vendor/github.com/prometheus/client_golang/prometheus/wrap.go index 25da157f1..2ed128506 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/wrap.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/wrap.go @@ -63,7 +63,7 @@ func WrapRegistererWith(labels Labels, reg Registerer) Registerer { // metric names that are standardized across applications, as that would break // horizontal monitoring, for example the metrics provided by the Go collector // (see NewGoCollector) and the process collector (see NewProcessCollector). (In -// fact, those metrics are already prefixed with “go_” or “process_”, +// fact, those metrics are already prefixed with "go_" or "process_", // respectively.) // // Conflicts between Collectors registered through the original Registerer with @@ -78,6 +78,40 @@ func WrapRegistererWithPrefix(prefix string, reg Registerer) Registerer { } } +// WrapCollectorWith returns a Collector wrapping the provided Collector. The +// wrapped Collector will add the provided Labels to all Metrics it collects (as +// ConstLabels). The Metrics collected by the unmodified Collector must not +// duplicate any of those labels. +// +// WrapCollectorWith can be useful to work with multiple instances of a third +// party library that does not expose enough flexibility on the lifecycle of its +// registered metrics. +// For example, let's say you have a foo.New(reg Registerer) constructor that +// registers metrics but never unregisters them, and you want to create multiple +// instances of foo.Foo with different labels. +// The way to achieve that, is to create a new Registry, pass it to foo.New, +// then use WrapCollectorWith to wrap that Registry with the desired labels and +// register that as a collector in your main Registry. +// Then you can un-register the wrapped collector effectively un-registering the +// metrics registered by foo.New. +func WrapCollectorWith(labels Labels, c Collector) Collector { + return &wrappingCollector{ + wrappedCollector: c, + labels: labels, + } +} + +// WrapCollectorWithPrefix returns a Collector wrapping the provided Collector. The +// wrapped Collector will add the provided prefix to the name of all Metrics it collects. +// +// See the documentation of WrapCollectorWith for more details on the use case. +func WrapCollectorWithPrefix(prefix string, c Collector) Collector { + return &wrappingCollector{ + wrappedCollector: c, + prefix: prefix, + } +} + type wrappingRegisterer struct { wrappedRegisterer Registerer prefix string diff --git a/vendor/golang.org/x/net/http2/http2.go b/vendor/golang.org/x/net/http2/http2.go index 6c18ea230..ea5ae629f 100644 --- a/vendor/golang.org/x/net/http2/http2.go +++ b/vendor/golang.org/x/net/http2/http2.go @@ -11,8 +11,6 @@ // requires Go 1.6 or later) // // See https://http2.github.io/ for more information on HTTP/2. -// -// See https://http2.golang.org/ for a test server running this code. package http2 // import "golang.org/x/net/http2" import ( diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh index 6ab02b6c3..d1c8b2640 100644 --- a/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -349,6 +349,9 @@ struct ltchars { #define _HIDIOCGRAWPHYS HIDIOCGRAWPHYS(_HIDIOCGRAWPHYS_LEN) #define _HIDIOCGRAWUNIQ HIDIOCGRAWUNIQ(_HIDIOCGRAWUNIQ_LEN) +// Renamed in v6.16, commit c6d732c38f93 ("net: ethtool: remove duplicate defines for family info") +#define ETHTOOL_FAMILY_NAME ETHTOOL_GENL_NAME +#define ETHTOOL_FAMILY_VERSION ETHTOOL_GENL_VERSION ' includes_NetBSD=' diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin.go b/vendor/golang.org/x/sys/unix/syscall_darwin.go index 798f61ad3..7838ca5db 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin.go @@ -602,14 +602,9 @@ func Connectx(fd int, srcIf uint32, srcAddr, dstAddr Sockaddr, associd SaeAssocI return } -// sys connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) const minIovec = 8 func Readv(fd int, iovs [][]byte) (n int, err error) { - if !darwinKernelVersionMin(11, 0, 0) { - return 0, ENOSYS - } - iovecs := make([]Iovec, 0, minIovec) iovecs = appendBytes(iovecs, iovs) n, err = readv(fd, iovecs) @@ -618,9 +613,6 @@ func Readv(fd int, iovs [][]byte) (n int, err error) { } func Preadv(fd int, iovs [][]byte, offset int64) (n int, err error) { - if !darwinKernelVersionMin(11, 0, 0) { - return 0, ENOSYS - } iovecs := make([]Iovec, 0, minIovec) iovecs = appendBytes(iovecs, iovs) n, err = preadv(fd, iovecs, offset) @@ -629,10 +621,6 @@ func Preadv(fd int, iovs [][]byte, offset int64) (n int, err error) { } func Writev(fd int, iovs [][]byte) (n int, err error) { - if !darwinKernelVersionMin(11, 0, 0) { - return 0, ENOSYS - } - iovecs := make([]Iovec, 0, minIovec) iovecs = appendBytes(iovecs, iovs) if raceenabled { @@ -644,10 +632,6 @@ func Writev(fd int, iovs [][]byte) (n int, err error) { } func Pwritev(fd int, iovs [][]byte, offset int64) (n int, err error) { - if !darwinKernelVersionMin(11, 0, 0) { - return 0, ENOSYS - } - iovecs := make([]Iovec, 0, minIovec) iovecs = appendBytes(iovecs, iovs) if raceenabled { @@ -707,45 +691,7 @@ func readvRacedetect(iovecs []Iovec, n int, err error) { } } -func darwinMajorMinPatch() (maj, min, patch int, err error) { - var un Utsname - err = Uname(&un) - if err != nil { - return - } - - var mmp [3]int - c := 0 -Loop: - for _, b := range un.Release[:] { - switch { - case b >= '0' && b <= '9': - mmp[c] = 10*mmp[c] + int(b-'0') - case b == '.': - c++ - if c > 2 { - return 0, 0, 0, ENOTSUP - } - case b == 0: - break Loop - default: - return 0, 0, 0, ENOTSUP - } - } - if c != 2 { - return 0, 0, 0, ENOTSUP - } - return mmp[0], mmp[1], mmp[2], nil -} - -func darwinKernelVersionMin(maj, min, patch int) bool { - actualMaj, actualMin, actualPatch, err := darwinMajorMinPatch() - if err != nil { - return false - } - return actualMaj > maj || actualMaj == maj && (actualMin > min || actualMin == min && actualPatch >= patch) -} - +//sys connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) //sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) //sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error) diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux.go b/vendor/golang.org/x/sys/unix/zerrors_linux.go index 9e7a6c5a4..b6db27d93 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -328,6 +328,8 @@ const ( AUDIT_KERNEL = 0x7d0 AUDIT_KERNEL_OTHER = 0x524 AUDIT_KERN_MODULE = 0x532 + AUDIT_LANDLOCK_ACCESS = 0x58f + AUDIT_LANDLOCK_DOMAIN = 0x590 AUDIT_LAST_FEATURE = 0x1 AUDIT_LAST_KERN_ANOM_MSG = 0x707 AUDIT_LAST_USER_MSG = 0x4af @@ -492,6 +494,7 @@ const ( BPF_F_BEFORE = 0x8 BPF_F_ID = 0x20 BPF_F_NETFILTER_IP_DEFRAG = 0x1 + BPF_F_PREORDER = 0x40 BPF_F_QUERY_EFFECTIVE = 0x1 BPF_F_REDIRECT_FLAGS = 0x19 BPF_F_REPLACE = 0x4 @@ -528,6 +531,7 @@ const ( BPF_LDX = 0x1 BPF_LEN = 0x80 BPF_LL_OFF = -0x200000 + BPF_LOAD_ACQ = 0x100 BPF_LSH = 0x60 BPF_MAJOR_VERSION = 0x1 BPF_MAXINSNS = 0x1000 @@ -555,6 +559,7 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_ST = 0x2 + BPF_STORE_REL = 0x110 BPF_STX = 0x3 BPF_SUB = 0x10 BPF_TAG_SIZE = 0x8 @@ -844,9 +849,9 @@ const ( DM_UUID_FLAG = 0x4000 DM_UUID_LEN = 0x81 DM_VERSION = 0xc138fd00 - DM_VERSION_EXTRA = "-ioctl (2025-01-17)" + DM_VERSION_EXTRA = "-ioctl (2025-04-28)" DM_VERSION_MAJOR = 0x4 - DM_VERSION_MINOR = 0x31 + DM_VERSION_MINOR = 0x32 DM_VERSION_PATCHLEVEL = 0x0 DT_BLK = 0x6 DT_CHR = 0x2 @@ -937,9 +942,6 @@ const ( EPOLL_CTL_MOD = 0x3 EPOLL_IOC_TYPE = 0x8a EROFS_SUPER_MAGIC_V1 = 0xe0f5e1e2 - ESP_V4_FLOW = 0xa - ESP_V6_FLOW = 0xc - ETHER_FLOW = 0x12 ETHTOOL_BUSINFO_LEN = 0x20 ETHTOOL_EROMVERS_LEN = 0x20 ETHTOOL_FAMILY_NAME = "ethtool" @@ -1213,6 +1215,7 @@ const ( FAN_EVENT_INFO_TYPE_DFID_NAME = 0x2 FAN_EVENT_INFO_TYPE_ERROR = 0x5 FAN_EVENT_INFO_TYPE_FID = 0x1 + FAN_EVENT_INFO_TYPE_MNT = 0x7 FAN_EVENT_INFO_TYPE_NEW_DFID_NAME = 0xc FAN_EVENT_INFO_TYPE_OLD_DFID_NAME = 0xa FAN_EVENT_INFO_TYPE_PIDFD = 0x4 @@ -1231,9 +1234,12 @@ const ( FAN_MARK_IGNORED_SURV_MODIFY = 0x40 FAN_MARK_IGNORE_SURV = 0x440 FAN_MARK_INODE = 0x0 + FAN_MARK_MNTNS = 0x110 FAN_MARK_MOUNT = 0x10 FAN_MARK_ONLYDIR = 0x8 FAN_MARK_REMOVE = 0x2 + FAN_MNT_ATTACH = 0x1000000 + FAN_MNT_DETACH = 0x2000000 FAN_MODIFY = 0x2 FAN_MOVE = 0xc0 FAN_MOVED_FROM = 0x40 @@ -1255,6 +1261,7 @@ const ( FAN_REPORT_DIR_FID = 0x400 FAN_REPORT_FD_ERROR = 0x2000 FAN_REPORT_FID = 0x200 + FAN_REPORT_MNT = 0x4000 FAN_REPORT_NAME = 0x800 FAN_REPORT_PIDFD = 0x80 FAN_REPORT_TARGET_FID = 0x1000 @@ -1274,6 +1281,7 @@ const ( FIB_RULE_PERMANENT = 0x1 FIB_RULE_UNRESOLVED = 0x4 FIDEDUPERANGE = 0xc0189436 + FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED = 0x1 FSCRYPT_KEY_DESCRIPTOR_SIZE = 0x8 FSCRYPT_KEY_DESC_PREFIX = "fscrypt:" FSCRYPT_KEY_DESC_PREFIX_SIZE = 0x8 @@ -1582,7 +1590,6 @@ const ( IPV6_DONTFRAG = 0x3e IPV6_DROP_MEMBERSHIP = 0x15 IPV6_DSTOPTS = 0x3b - IPV6_FLOW = 0x11 IPV6_FREEBIND = 0x4e IPV6_HDRINCL = 0x24 IPV6_HOPLIMIT = 0x34 @@ -1633,7 +1640,6 @@ const ( IPV6_TRANSPARENT = 0x4b IPV6_UNICAST_HOPS = 0x10 IPV6_UNICAST_IF = 0x4c - IPV6_USER_FLOW = 0xe IPV6_V6ONLY = 0x1a IPV6_VERSION = 0x60 IPV6_VERSION_MASK = 0xf0 @@ -1695,7 +1701,6 @@ const ( IP_TTL = 0x2 IP_UNBLOCK_SOURCE = 0x25 IP_UNICAST_IF = 0x32 - IP_USER_FLOW = 0xd IP_XFRM_POLICY = 0x11 ISOFS_SUPER_MAGIC = 0x9660 ISTRIP = 0x20 @@ -1817,7 +1822,11 @@ const ( LANDLOCK_ACCESS_FS_WRITE_FILE = 0x2 LANDLOCK_ACCESS_NET_BIND_TCP = 0x1 LANDLOCK_ACCESS_NET_CONNECT_TCP = 0x2 + LANDLOCK_CREATE_RULESET_ERRATA = 0x2 LANDLOCK_CREATE_RULESET_VERSION = 0x1 + LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON = 0x2 + LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF = 0x1 + LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF = 0x4 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET = 0x1 LANDLOCK_SCOPE_SIGNAL = 0x2 LINUX_REBOOT_CMD_CAD_OFF = 0x0 @@ -2493,6 +2502,10 @@ const ( PR_FP_EXC_UND = 0x40000 PR_FP_MODE_FR = 0x1 PR_FP_MODE_FRE = 0x2 + PR_FUTEX_HASH = 0x4e + PR_FUTEX_HASH_GET_IMMUTABLE = 0x3 + PR_FUTEX_HASH_GET_SLOTS = 0x2 + PR_FUTEX_HASH_SET_SLOTS = 0x1 PR_GET_AUXV = 0x41555856 PR_GET_CHILD_SUBREAPER = 0x25 PR_GET_DUMPABLE = 0x3 @@ -2652,6 +2665,10 @@ const ( PR_TAGGED_ADDR_ENABLE = 0x1 PR_TASK_PERF_EVENTS_DISABLE = 0x1f PR_TASK_PERF_EVENTS_ENABLE = 0x20 + PR_TIMER_CREATE_RESTORE_IDS = 0x4d + PR_TIMER_CREATE_RESTORE_IDS_GET = 0x2 + PR_TIMER_CREATE_RESTORE_IDS_OFF = 0x0 + PR_TIMER_CREATE_RESTORE_IDS_ON = 0x1 PR_TIMING_STATISTICAL = 0x0 PR_TIMING_TIMESTAMP = 0x1 PR_TSC_ENABLE = 0x1 @@ -2732,6 +2749,7 @@ const ( PTRACE_SETREGSET = 0x4205 PTRACE_SETSIGINFO = 0x4203 PTRACE_SETSIGMASK = 0x420b + PTRACE_SET_SYSCALL_INFO = 0x4212 PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG = 0x4210 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 @@ -2982,6 +3000,7 @@ const ( RTPROT_NTK = 0xf RTPROT_OPENR = 0x63 RTPROT_OSPF = 0xbc + RTPROT_OVN = 0x54 RTPROT_RA = 0x9 RTPROT_REDIRECT = 0x1 RTPROT_RIP = 0xbd @@ -3336,7 +3355,7 @@ const ( TASKSTATS_GENL_NAME = "TASKSTATS" TASKSTATS_GENL_VERSION = 0x1 TASKSTATS_TYPE_MAX = 0x6 - TASKSTATS_VERSION = 0xf + TASKSTATS_VERSION = 0x10 TCIFLUSH = 0x0 TCIOFF = 0x2 TCIOFLUSH = 0x2 @@ -3406,8 +3425,6 @@ const ( TCP_TX_DELAY = 0x25 TCP_ULP = 0x1f TCP_USER_TIMEOUT = 0x12 - TCP_V4_FLOW = 0x1 - TCP_V6_FLOW = 0x5 TCP_WINDOW_CLAMP = 0xa TCP_ZEROCOPY_RECEIVE = 0x23 TFD_TIMER_ABSTIME = 0x1 @@ -3530,8 +3547,6 @@ const ( UDP_NO_CHECK6_RX = 0x66 UDP_NO_CHECK6_TX = 0x65 UDP_SEGMENT = 0x67 - UDP_V4_FLOW = 0x2 - UDP_V6_FLOW = 0x6 UMOUNT_NOFOLLOW = 0x8 USBDEVICE_SUPER_MAGIC = 0x9fa2 UTIME_NOW = 0x3fffffff @@ -3574,7 +3589,7 @@ const ( WDIOS_TEMPPANIC = 0x4 WDIOS_UNKNOWN = -0x1 WEXITED = 0x4 - WGALLOWEDIP_A_MAX = 0x3 + WGALLOWEDIP_A_MAX = 0x4 WGDEVICE_A_MAX = 0x8 WGPEER_A_MAX = 0xa WG_CMD_MAX = 0x1 @@ -3688,6 +3703,7 @@ const ( XDP_SHARED_UMEM = 0x1 XDP_STATISTICS = 0x7 XDP_TXMD_FLAGS_CHECKSUM = 0x2 + XDP_TXMD_FLAGS_LAUNCH_TIME = 0x4 XDP_TXMD_FLAGS_TIMESTAMP = 0x1 XDP_TX_METADATA = 0x2 XDP_TX_RING = 0x3 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index a8c421e29..1c37f9fbc 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -360,6 +361,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index 9a88d1813..6f54d34ae 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -361,6 +362,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index 7cb6a867e..783ec5c12 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -366,6 +367,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index d0ecd2c58..ca83d3ba1 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go index 7a2940ae0..607e611c0 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -353,6 +354,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index d14ca8f2e..b9cb5bd3c 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index 2da1bac1e..65b078a63 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index 28727514b..5298a3033 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index 7f287b54b..7bc557c87 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -359,6 +360,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go index 7e5f9e6aa..152399bb0 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go @@ -68,6 +68,7 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 @@ -414,6 +415,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x14 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x15 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index 37c87952f..1a1ce2409 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 @@ -418,6 +419,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x14 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x15 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index 522013361..4231a1fb5 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -68,6 +68,7 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 @@ -418,6 +419,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x14 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x15 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index 4bfe2b5b6..21c0e9526 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -350,6 +351,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index e3cffb869..f00d1cd7c 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -68,6 +68,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 ECCGETLAYOUT = 0x81484d11 ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 @@ -422,6 +423,7 @@ const ( SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go index c219c8db3..bc8d539e6 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -71,6 +71,7 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 ECCGETLAYOUT = 0x41484d11 ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 @@ -461,6 +462,7 @@ const ( SO_OOBINLINE = 0x100 SO_PASSCRED = 0x2 SO_PASSPIDFD = 0x55 + SO_PASSRIGHTS = 0x5c SO_PASSSEC = 0x1f SO_PEEK_OFF = 0x26 SO_PEERCRED = 0x40 diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go index c79aaff30..aca56ee49 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go @@ -462,4 +462,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go index 5eb450695..2ea1ef58c 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go @@ -385,4 +385,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go index 05e502974..d22c8af31 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go @@ -426,4 +426,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go index 38c53ec51..5ee264ae9 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go @@ -329,4 +329,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go index 31d2e71a1..f9f03ebf5 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go @@ -325,4 +325,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go index f4184a336..87c2118e8 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go @@ -446,4 +446,5 @@ const ( SYS_GETXATTRAT = 4464 SYS_LISTXATTRAT = 4465 SYS_REMOVEXATTRAT = 4466 + SYS_OPEN_TREE_ATTR = 4467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go index 05b996227..391ad102f 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go @@ -376,4 +376,5 @@ const ( SYS_GETXATTRAT = 5464 SYS_LISTXATTRAT = 5465 SYS_REMOVEXATTRAT = 5466 + SYS_OPEN_TREE_ATTR = 5467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go index 43a256e9e..565615775 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go @@ -376,4 +376,5 @@ const ( SYS_GETXATTRAT = 5464 SYS_LISTXATTRAT = 5465 SYS_REMOVEXATTRAT = 5466 + SYS_OPEN_TREE_ATTR = 5467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go index eea5ddfc2..0482b52e3 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go @@ -446,4 +446,5 @@ const ( SYS_GETXATTRAT = 4464 SYS_LISTXATTRAT = 4465 SYS_REMOVEXATTRAT = 4466 + SYS_OPEN_TREE_ATTR = 4467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go index 0d777bfbb..71806f08f 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go @@ -453,4 +453,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go index b44636502..e35a71058 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go @@ -425,4 +425,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go index 0c7d21c18..2aea47670 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go @@ -425,4 +425,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go index 840539169..6c9bb4e56 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go @@ -330,4 +330,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go index fcf1b790d..680bc9915 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go @@ -391,4 +391,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go index 52d15b5f9..620f27105 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go @@ -404,4 +404,5 @@ const ( SYS_GETXATTRAT = 464 SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux.go b/vendor/golang.org/x/sys/unix/ztypes_linux.go index 8bcac2835..cd236443f 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -115,7 +115,9 @@ type Statx_t struct { Atomic_write_unit_max uint32 Atomic_write_segments_max uint32 Dio_read_offset_align uint32 - _ [9]uint64 + Atomic_write_unit_max_opt uint32 + _ [1]uint32 + _ [8]uint64 } type Fsid struct { @@ -199,7 +201,8 @@ type FscryptAddKeyArg struct { Key_spec FscryptKeySpecifier Raw_size uint32 Key_id uint32 - _ [8]uint32 + Flags uint32 + _ [7]uint32 } type FscryptRemoveKeyArg struct { @@ -2317,6 +2320,11 @@ const ( NFT_CT_AVGPKT = 0x10 NFT_CT_ZONE = 0x11 NFT_CT_EVENTMASK = 0x12 + NFT_CT_SRC_IP = 0x13 + NFT_CT_DST_IP = 0x14 + NFT_CT_SRC_IP6 = 0x15 + NFT_CT_DST_IP6 = 0x16 + NFT_CT_ID = 0x17 NFTA_CT_UNSPEC = 0x0 NFTA_CT_DREG = 0x1 NFTA_CT_KEY = 0x2 @@ -2597,8 +2605,8 @@ const ( SOF_TIMESTAMPING_BIND_PHC = 0x8000 SOF_TIMESTAMPING_OPT_ID_TCP = 0x10000 - SOF_TIMESTAMPING_LAST = 0x20000 - SOF_TIMESTAMPING_MASK = 0x3ffff + SOF_TIMESTAMPING_LAST = 0x40000 + SOF_TIMESTAMPING_MASK = 0x7ffff SCM_TSTAMP_SND = 0x0 SCM_TSTAMP_SCHED = 0x1 @@ -4044,7 +4052,7 @@ const ( ETHTOOL_A_TSINFO_PHC_INDEX = 0x5 ETHTOOL_A_TSINFO_STATS = 0x6 ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER = 0x7 - ETHTOOL_A_TSINFO_MAX = 0x7 + ETHTOOL_A_TSINFO_MAX = 0x9 ETHTOOL_A_CABLE_TEST_UNSPEC = 0x0 ETHTOOL_A_CABLE_TEST_HEADER = 0x1 ETHTOOL_A_CABLE_TEST_MAX = 0x1 @@ -4130,6 +4138,19 @@ const ( ETHTOOL_A_TUNNEL_INFO_MAX = 0x2 ) +const ( + TCP_V4_FLOW = 0x1 + UDP_V4_FLOW = 0x2 + TCP_V6_FLOW = 0x5 + UDP_V6_FLOW = 0x6 + ESP_V4_FLOW = 0xa + ESP_V6_FLOW = 0xc + IP_USER_FLOW = 0xd + IPV6_USER_FLOW = 0xe + IPV6_FLOW = 0x11 + ETHER_FLOW = 0x12 +) + const SPEED_UNKNOWN = -0x1 type EthtoolDrvinfo struct { @@ -4780,7 +4801,7 @@ const ( NL80211_ATTR_MAC_HINT = 0xc8 NL80211_ATTR_MAC_MASK = 0xd7 NL80211_ATTR_MAX_AP_ASSOC_STA = 0xca - NL80211_ATTR_MAX = 0x150 + NL80211_ATTR_MAX = 0x151 NL80211_ATTR_MAX_CRIT_PROT_DURATION = 0xb4 NL80211_ATTR_MAX_CSA_COUNTERS = 0xce NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS = 0x143 @@ -5414,7 +5435,7 @@ const ( NL80211_FREQUENCY_ATTR_GO_CONCURRENT = 0xf NL80211_FREQUENCY_ATTR_INDOOR_ONLY = 0xe NL80211_FREQUENCY_ATTR_IR_CONCURRENT = 0xf - NL80211_FREQUENCY_ATTR_MAX = 0x21 + NL80211_FREQUENCY_ATTR_MAX = 0x22 NL80211_FREQUENCY_ATTR_MAX_TX_POWER = 0x6 NL80211_FREQUENCY_ATTR_NO_10MHZ = 0x11 NL80211_FREQUENCY_ATTR_NO_160MHZ = 0xc @@ -5530,7 +5551,7 @@ const ( NL80211_MAX_SUPP_SELECTORS = 0x80 NL80211_MBSSID_CONFIG_ATTR_EMA = 0x5 NL80211_MBSSID_CONFIG_ATTR_INDEX = 0x3 - NL80211_MBSSID_CONFIG_ATTR_MAX = 0x5 + NL80211_MBSSID_CONFIG_ATTR_MAX = 0x6 NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY = 0x2 NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES = 0x1 NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX = 0x4 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index 62db85f6c..485f2d3a1 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -282,19 +282,13 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 - Cpu_delay_max uint64 - Cpu_delay_min uint64 Blkio_count uint64 Blkio_delay_total uint64 - Blkio_delay_max uint64 - Blkio_delay_min uint64 Swapin_count uint64 Swapin_delay_total uint64 - Swapin_delay_max uint64 - Swapin_delay_min uint64 Cpu_run_real_total uint64 Cpu_run_virtual_total uint64 Ac_comm [32]int8 @@ -330,17 +324,11 @@ type Taskstats struct { Cpu_scaled_run_real_total uint64 Freepages_count uint64 Freepages_delay_total uint64 - Freepages_delay_max uint64 - Freepages_delay_min uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Thrashing_delay_max uint64 - Thrashing_delay_min uint64 Ac_btime64 uint64 Compact_count uint64 Compact_delay_total uint64 - Compact_delay_max uint64 - Compact_delay_min uint64 Ac_tgid uint32 _ [4]byte Ac_tgetime uint64 @@ -348,10 +336,22 @@ type Taskstats struct { Ac_exe_inode uint64 Wpcopy_count uint64 Wpcopy_delay_total uint64 - Wpcopy_delay_max uint64 - Wpcopy_delay_min uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 } diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index 7d89d648d..ecbd1ad8b 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -300,16 +300,10 @@ type Taskstats struct { Ac_nice uint8 Cpu_count uint64 Cpu_delay_total uint64 - Cpu_delay_max uint64 - Cpu_delay_min uint64 Blkio_count uint64 Blkio_delay_total uint64 - Blkio_delay_max uint64 - Blkio_delay_min uint64 Swapin_count uint64 Swapin_delay_total uint64 - Swapin_delay_max uint64 - Swapin_delay_min uint64 Cpu_run_real_total uint64 Cpu_run_virtual_total uint64 Ac_comm [32]int8 @@ -344,27 +338,33 @@ type Taskstats struct { Cpu_scaled_run_real_total uint64 Freepages_count uint64 Freepages_delay_total uint64 - Freepages_delay_max uint64 - Freepages_delay_min uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Thrashing_delay_max uint64 - Thrashing_delay_min uint64 Ac_btime64 uint64 Compact_count uint64 Compact_delay_total uint64 - Compact_delay_max uint64 - Compact_delay_min uint64 Ac_tgid uint32 Ac_tgetime uint64 Ac_exe_dev uint64 Ac_exe_inode uint64 Wpcopy_count uint64 Wpcopy_delay_total uint64 - Wpcopy_delay_max uint64 - Wpcopy_delay_min uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 } diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index 9c0b39eec..02f0463a4 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -91,7 +91,7 @@ type Stat_t struct { Gid uint32 Rdev uint64 _ uint16 - _ [4]byte + _ [6]byte Size int64 Blksize int32 _ [4]byte @@ -273,19 +273,13 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 - Cpu_delay_max uint64 - Cpu_delay_min uint64 Blkio_count uint64 Blkio_delay_total uint64 - Blkio_delay_max uint64 - Blkio_delay_min uint64 Swapin_count uint64 Swapin_delay_total uint64 - Swapin_delay_max uint64 - Swapin_delay_min uint64 Cpu_run_real_total uint64 Cpu_run_virtual_total uint64 Ac_comm [32]uint8 @@ -321,17 +315,11 @@ type Taskstats struct { Cpu_scaled_run_real_total uint64 Freepages_count uint64 Freepages_delay_total uint64 - Freepages_delay_max uint64 - Freepages_delay_min uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Thrashing_delay_max uint64 - Thrashing_delay_min uint64 Ac_btime64 uint64 Compact_count uint64 Compact_delay_total uint64 - Compact_delay_max uint64 - Compact_delay_min uint64 Ac_tgid uint32 _ [4]byte Ac_tgetime uint64 @@ -339,10 +327,22 @@ type Taskstats struct { Ac_exe_inode uint64 Wpcopy_count uint64 Wpcopy_delay_total uint64 - Wpcopy_delay_max uint64 - Wpcopy_delay_min uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 } diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index de9c7ff36..6f4d400d2 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -279,16 +279,10 @@ type Taskstats struct { Ac_nice uint8 Cpu_count uint64 Cpu_delay_total uint64 - Cpu_delay_max uint64 - Cpu_delay_min uint64 Blkio_count uint64 Blkio_delay_total uint64 - Blkio_delay_max uint64 - Blkio_delay_min uint64 Swapin_count uint64 Swapin_delay_total uint64 - Swapin_delay_max uint64 - Swapin_delay_min uint64 Cpu_run_real_total uint64 Cpu_run_virtual_total uint64 Ac_comm [32]int8 @@ -323,27 +317,33 @@ type Taskstats struct { Cpu_scaled_run_real_total uint64 Freepages_count uint64 Freepages_delay_total uint64 - Freepages_delay_max uint64 - Freepages_delay_min uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Thrashing_delay_max uint64 - Thrashing_delay_min uint64 Ac_btime64 uint64 Compact_count uint64 Compact_delay_total uint64 - Compact_delay_max uint64 - Compact_delay_min uint64 Ac_tgid uint32 Ac_tgetime uint64 Ac_exe_dev uint64 Ac_exe_inode uint64 Wpcopy_count uint64 Wpcopy_delay_total uint64 - Wpcopy_delay_max uint64 - Wpcopy_delay_min uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 } diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go index 2336bd2bf..cd532cfa5 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go @@ -280,16 +280,10 @@ type Taskstats struct { Ac_nice uint8 Cpu_count uint64 Cpu_delay_total uint64 - Cpu_delay_max uint64 - Cpu_delay_min uint64 Blkio_count uint64 Blkio_delay_total uint64 - Blkio_delay_max uint64 - Blkio_delay_min uint64 Swapin_count uint64 Swapin_delay_total uint64 - Swapin_delay_max uint64 - Swapin_delay_min uint64 Cpu_run_real_total uint64 Cpu_run_virtual_total uint64 Ac_comm [32]int8 @@ -324,27 +318,33 @@ type Taskstats struct { Cpu_scaled_run_real_total uint64 Freepages_count uint64 Freepages_delay_total uint64 - Freepages_delay_max uint64 - Freepages_delay_min uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Thrashing_delay_max uint64 - Thrashing_delay_min uint64 Ac_btime64 uint64 Compact_count uint64 Compact_delay_total uint64 - Compact_delay_max uint64 - Compact_delay_min uint64 Ac_tgid uint32 Ac_tgetime uint64 Ac_exe_dev uint64 Ac_exe_inode uint64 Wpcopy_count uint64 Wpcopy_delay_total uint64 - Wpcopy_delay_max uint64 - Wpcopy_delay_min uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 } diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index 4711f0be1..413362085 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -278,19 +278,13 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 - Cpu_delay_max uint64 - Cpu_delay_min uint64 Blkio_count uint64 Blkio_delay_total uint64 - Blkio_delay_max uint64 - Blkio_delay_min uint64 Swapin_count uint64 Swapin_delay_total uint64 - Swapin_delay_max uint64 - Swapin_delay_min uint64 Cpu_run_real_total uint64 Cpu_run_virtual_total uint64 Ac_comm [32]int8 @@ -326,17 +320,11 @@ type Taskstats struct { Cpu_scaled_run_real_total uint64 Freepages_count uint64 Freepages_delay_total uint64 - Freepages_delay_max uint64 - Freepages_delay_min uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Thrashing_delay_max uint64 - Thrashing_delay_min uint64 Ac_btime64 uint64 Compact_count uint64 Compact_delay_total uint64 - Compact_delay_max uint64 - Compact_delay_min uint64 Ac_tgid uint32 _ [4]byte Ac_tgetime uint64 @@ -344,10 +332,22 @@ type Taskstats struct { Ac_exe_inode uint64 Wpcopy_count uint64 Wpcopy_delay_total uint64 - Wpcopy_delay_max uint64 - Wpcopy_delay_min uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 } diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index ab99a34b9..eaa37eb71 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -282,16 +282,10 @@ type Taskstats struct { Ac_nice uint8 Cpu_count uint64 Cpu_delay_total uint64 - Cpu_delay_max uint64 - Cpu_delay_min uint64 Blkio_count uint64 Blkio_delay_total uint64 - Blkio_delay_max uint64 - Blkio_delay_min uint64 Swapin_count uint64 Swapin_delay_total uint64 - Swapin_delay_max uint64 - Swapin_delay_min uint64 Cpu_run_real_total uint64 Cpu_run_virtual_total uint64 Ac_comm [32]int8 @@ -326,27 +320,33 @@ type Taskstats struct { Cpu_scaled_run_real_total uint64 Freepages_count uint64 Freepages_delay_total uint64 - Freepages_delay_max uint64 - Freepages_delay_min uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Thrashing_delay_max uint64 - Thrashing_delay_min uint64 Ac_btime64 uint64 Compact_count uint64 Compact_delay_total uint64 - Compact_delay_max uint64 - Compact_delay_min uint64 Ac_tgid uint32 Ac_tgetime uint64 Ac_exe_dev uint64 Ac_exe_inode uint64 Wpcopy_count uint64 Wpcopy_delay_total uint64 - Wpcopy_delay_max uint64 - Wpcopy_delay_min uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 } diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index 04c9866e3..98ae6a1e4 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -282,16 +282,10 @@ type Taskstats struct { Ac_nice uint8 Cpu_count uint64 Cpu_delay_total uint64 - Cpu_delay_max uint64 - Cpu_delay_min uint64 Blkio_count uint64 Blkio_delay_total uint64 - Blkio_delay_max uint64 - Blkio_delay_min uint64 Swapin_count uint64 Swapin_delay_total uint64 - Swapin_delay_max uint64 - Swapin_delay_min uint64 Cpu_run_real_total uint64 Cpu_run_virtual_total uint64 Ac_comm [32]int8 @@ -326,27 +320,33 @@ type Taskstats struct { Cpu_scaled_run_real_total uint64 Freepages_count uint64 Freepages_delay_total uint64 - Freepages_delay_max uint64 - Freepages_delay_min uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Thrashing_delay_max uint64 - Thrashing_delay_min uint64 Ac_btime64 uint64 Compact_count uint64 Compact_delay_total uint64 - Compact_delay_max uint64 - Compact_delay_min uint64 Ac_tgid uint32 Ac_tgetime uint64 Ac_exe_dev uint64 Ac_exe_inode uint64 Wpcopy_count uint64 Wpcopy_delay_total uint64 - Wpcopy_delay_max uint64 - Wpcopy_delay_min uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 } diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index 60aa69f61..cae196159 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -278,19 +278,13 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 - Cpu_delay_max uint64 - Cpu_delay_min uint64 Blkio_count uint64 Blkio_delay_total uint64 - Blkio_delay_max uint64 - Blkio_delay_min uint64 Swapin_count uint64 Swapin_delay_total uint64 - Swapin_delay_max uint64 - Swapin_delay_min uint64 Cpu_run_real_total uint64 Cpu_run_virtual_total uint64 Ac_comm [32]int8 @@ -326,17 +320,11 @@ type Taskstats struct { Cpu_scaled_run_real_total uint64 Freepages_count uint64 Freepages_delay_total uint64 - Freepages_delay_max uint64 - Freepages_delay_min uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Thrashing_delay_max uint64 - Thrashing_delay_min uint64 Ac_btime64 uint64 Compact_count uint64 Compact_delay_total uint64 - Compact_delay_max uint64 - Compact_delay_min uint64 Ac_tgid uint32 _ [4]byte Ac_tgetime uint64 @@ -344,10 +332,22 @@ type Taskstats struct { Ac_exe_inode uint64 Wpcopy_count uint64 Wpcopy_delay_total uint64 - Wpcopy_delay_max uint64 - Wpcopy_delay_min uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 } diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go index cb4fad785..6ce3b4e02 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go @@ -90,7 +90,7 @@ type Stat_t struct { Gid uint32 Rdev uint64 _ uint16 - _ [4]byte + _ [6]byte Size int64 Blksize int32 _ [4]byte @@ -285,19 +285,13 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 - Cpu_delay_max uint64 - Cpu_delay_min uint64 Blkio_count uint64 Blkio_delay_total uint64 - Blkio_delay_max uint64 - Blkio_delay_min uint64 Swapin_count uint64 Swapin_delay_total uint64 - Swapin_delay_max uint64 - Swapin_delay_min uint64 Cpu_run_real_total uint64 Cpu_run_virtual_total uint64 Ac_comm [32]uint8 @@ -333,17 +327,11 @@ type Taskstats struct { Cpu_scaled_run_real_total uint64 Freepages_count uint64 Freepages_delay_total uint64 - Freepages_delay_max uint64 - Freepages_delay_min uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Thrashing_delay_max uint64 - Thrashing_delay_min uint64 Ac_btime64 uint64 Compact_count uint64 Compact_delay_total uint64 - Compact_delay_max uint64 - Compact_delay_min uint64 Ac_tgid uint32 _ [4]byte Ac_tgetime uint64 @@ -351,10 +339,22 @@ type Taskstats struct { Ac_exe_inode uint64 Wpcopy_count uint64 Wpcopy_delay_total uint64 - Wpcopy_delay_max uint64 - Wpcopy_delay_min uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 } diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index 60272cfce..c7429c6a1 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -289,16 +289,10 @@ type Taskstats struct { Ac_nice uint8 Cpu_count uint64 Cpu_delay_total uint64 - Cpu_delay_max uint64 - Cpu_delay_min uint64 Blkio_count uint64 Blkio_delay_total uint64 - Blkio_delay_max uint64 - Blkio_delay_min uint64 Swapin_count uint64 Swapin_delay_total uint64 - Swapin_delay_max uint64 - Swapin_delay_min uint64 Cpu_run_real_total uint64 Cpu_run_virtual_total uint64 Ac_comm [32]uint8 @@ -333,27 +327,33 @@ type Taskstats struct { Cpu_scaled_run_real_total uint64 Freepages_count uint64 Freepages_delay_total uint64 - Freepages_delay_max uint64 - Freepages_delay_min uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Thrashing_delay_max uint64 - Thrashing_delay_min uint64 Ac_btime64 uint64 Compact_count uint64 Compact_delay_total uint64 - Compact_delay_max uint64 - Compact_delay_min uint64 Ac_tgid uint32 Ac_tgetime uint64 Ac_exe_dev uint64 Ac_exe_inode uint64 Wpcopy_count uint64 Wpcopy_delay_total uint64 - Wpcopy_delay_max uint64 - Wpcopy_delay_min uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 } diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index 3f5b91bc0..4bf4baf4c 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -289,16 +289,10 @@ type Taskstats struct { Ac_nice uint8 Cpu_count uint64 Cpu_delay_total uint64 - Cpu_delay_max uint64 - Cpu_delay_min uint64 Blkio_count uint64 Blkio_delay_total uint64 - Blkio_delay_max uint64 - Blkio_delay_min uint64 Swapin_count uint64 Swapin_delay_total uint64 - Swapin_delay_max uint64 - Swapin_delay_min uint64 Cpu_run_real_total uint64 Cpu_run_virtual_total uint64 Ac_comm [32]uint8 @@ -333,27 +327,33 @@ type Taskstats struct { Cpu_scaled_run_real_total uint64 Freepages_count uint64 Freepages_delay_total uint64 - Freepages_delay_max uint64 - Freepages_delay_min uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Thrashing_delay_max uint64 - Thrashing_delay_min uint64 Ac_btime64 uint64 Compact_count uint64 Compact_delay_total uint64 - Compact_delay_max uint64 - Compact_delay_min uint64 Ac_tgid uint32 Ac_tgetime uint64 Ac_exe_dev uint64 Ac_exe_inode uint64 Wpcopy_count uint64 Wpcopy_delay_total uint64 - Wpcopy_delay_max uint64 - Wpcopy_delay_min uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 } diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index 51550f15a..e9709d70a 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -307,16 +307,10 @@ type Taskstats struct { Ac_nice uint8 Cpu_count uint64 Cpu_delay_total uint64 - Cpu_delay_max uint64 - Cpu_delay_min uint64 Blkio_count uint64 Blkio_delay_total uint64 - Blkio_delay_max uint64 - Blkio_delay_min uint64 Swapin_count uint64 Swapin_delay_total uint64 - Swapin_delay_max uint64 - Swapin_delay_min uint64 Cpu_run_real_total uint64 Cpu_run_virtual_total uint64 Ac_comm [32]uint8 @@ -351,27 +345,33 @@ type Taskstats struct { Cpu_scaled_run_real_total uint64 Freepages_count uint64 Freepages_delay_total uint64 - Freepages_delay_max uint64 - Freepages_delay_min uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Thrashing_delay_max uint64 - Thrashing_delay_min uint64 Ac_btime64 uint64 Compact_count uint64 Compact_delay_total uint64 - Compact_delay_max uint64 - Compact_delay_min uint64 Ac_tgid uint32 Ac_tgetime uint64 Ac_exe_dev uint64 Ac_exe_inode uint64 Wpcopy_count uint64 Wpcopy_delay_total uint64 - Wpcopy_delay_max uint64 - Wpcopy_delay_min uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 } diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index 3239e50e0..fb44268ca 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -302,16 +302,10 @@ type Taskstats struct { Ac_nice uint8 Cpu_count uint64 Cpu_delay_total uint64 - Cpu_delay_max uint64 - Cpu_delay_min uint64 Blkio_count uint64 Blkio_delay_total uint64 - Blkio_delay_max uint64 - Blkio_delay_min uint64 Swapin_count uint64 Swapin_delay_total uint64 - Swapin_delay_max uint64 - Swapin_delay_min uint64 Cpu_run_real_total uint64 Cpu_run_virtual_total uint64 Ac_comm [32]int8 @@ -346,27 +340,33 @@ type Taskstats struct { Cpu_scaled_run_real_total uint64 Freepages_count uint64 Freepages_delay_total uint64 - Freepages_delay_max uint64 - Freepages_delay_min uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Thrashing_delay_max uint64 - Thrashing_delay_min uint64 Ac_btime64 uint64 Compact_count uint64 Compact_delay_total uint64 - Compact_delay_max uint64 - Compact_delay_min uint64 Ac_tgid uint32 Ac_tgetime uint64 Ac_exe_dev uint64 Ac_exe_inode uint64 Wpcopy_count uint64 Wpcopy_delay_total uint64 - Wpcopy_delay_max uint64 - Wpcopy_delay_min uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 } diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go index faf200278..9c38265c7 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -284,16 +284,10 @@ type Taskstats struct { Ac_nice uint8 Cpu_count uint64 Cpu_delay_total uint64 - Cpu_delay_max uint64 - Cpu_delay_min uint64 Blkio_count uint64 Blkio_delay_total uint64 - Blkio_delay_max uint64 - Blkio_delay_min uint64 Swapin_count uint64 Swapin_delay_total uint64 - Swapin_delay_max uint64 - Swapin_delay_min uint64 Cpu_run_real_total uint64 Cpu_run_virtual_total uint64 Ac_comm [32]int8 @@ -328,27 +322,33 @@ type Taskstats struct { Cpu_scaled_run_real_total uint64 Freepages_count uint64 Freepages_delay_total uint64 - Freepages_delay_max uint64 - Freepages_delay_min uint64 Thrashing_count uint64 Thrashing_delay_total uint64 - Thrashing_delay_max uint64 - Thrashing_delay_min uint64 Ac_btime64 uint64 Compact_count uint64 Compact_delay_total uint64 - Compact_delay_max uint64 - Compact_delay_min uint64 Ac_tgid uint32 Ac_tgetime uint64 Ac_exe_dev uint64 Ac_exe_inode uint64 Wpcopy_count uint64 Wpcopy_delay_total uint64 - Wpcopy_delay_max uint64 - Wpcopy_delay_min uint64 Irq_count uint64 Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 } diff --git a/vendor/golang.org/x/term/term_windows.go b/vendor/golang.org/x/term/term_windows.go index df6bf948e..0ddd81c02 100644 --- a/vendor/golang.org/x/term/term_windows.go +++ b/vendor/golang.org/x/term/term_windows.go @@ -20,12 +20,14 @@ func isTerminal(fd int) bool { return err == nil } +// This is intended to be used on a console input handle. +// See https://learn.microsoft.com/en-us/windows/console/setconsolemode func makeRaw(fd int) (*State, error) { var st uint32 if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { return nil, err } - raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT) + raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT) raw |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil { return nil, err diff --git a/vendor/golang.org/x/term/terminal.go b/vendor/golang.org/x/term/terminal.go index 13e9a64ad..bddb2e2ae 100644 --- a/vendor/golang.org/x/term/terminal.go +++ b/vendor/golang.org/x/term/terminal.go @@ -146,6 +146,7 @@ const ( keyCtrlD = 4 keyCtrlU = 21 keyEnter = '\r' + keyLF = '\n' keyEscape = 27 keyBackspace = 127 keyUnknown = 0xd800 /* UTF-16 surrogate area */ + iota @@ -497,7 +498,7 @@ func (t *Terminal) historyAdd(entry string) { // handleKey processes the given key and, optionally, returns a line of text // that the user has entered. func (t *Terminal) handleKey(key rune) (line string, ok bool) { - if t.pasteActive && key != keyEnter { + if t.pasteActive && key != keyEnter && key != keyLF { t.addKeyToLine(key) return } @@ -567,7 +568,7 @@ func (t *Terminal) handleKey(key rune) (line string, ok bool) { t.setLine(runes, len(runes)) } } - case keyEnter: + case keyEnter, keyLF: t.moveCursorToPos(len(t.line)) t.queue([]rune("\r\n")) line = string(t.line) @@ -812,6 +813,10 @@ func (t *Terminal) readLine() (line string, err error) { if !t.pasteActive { lineIsPasted = false } + // If we have CR, consume LF if present (CRLF sequence) to avoid returning an extra empty line. + if key == keyEnter && len(rest) > 0 && rest[0] == keyLF { + rest = rest[1:] + } line, lineOk = t.handleKey(key) } if len(rest) > 0 { diff --git a/vendor/golang.org/x/tools/go/analysis/analysistest/analysistest.go b/vendor/golang.org/x/tools/go/analysis/analysistest/analysistest.go index 203123450..3f1721593 100644 --- a/vendor/golang.org/x/tools/go/analysis/analysistest/analysistest.go +++ b/vendor/golang.org/x/tools/go/analysis/analysistest/analysistest.go @@ -575,7 +575,7 @@ func check(t Testing, gopath string, act *checker.Action) { files := act.Package.OtherFiles // Hack: these two analyzers need to extract expectations from - // all configurations, so include the files are are usually + // all configurations, so include the files are usually // ignored. (This was previously a hack in the respective // analyzers' tests.) if act.Analyzer.Name == "buildtag" || act.Analyzer.Name == "directive" { diff --git a/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/flags.go b/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/flags.go index 6aefef258..18e01c40d 100644 --- a/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/flags.go +++ b/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/flags.go @@ -318,24 +318,32 @@ var vetLegacyFlags = map[string]string{ // If contextLines is nonnegative, it also prints the // offending line plus this many lines of context. func PrintPlain(out io.Writer, fset *token.FileSet, contextLines int, diag analysis.Diagnostic) { - posn := fset.Position(diag.Pos) - fmt.Fprintf(out, "%s: %s\n", posn, diag.Message) - - // show offending line plus N lines of context. - if contextLines >= 0 { - posn := fset.Position(diag.Pos) - end := fset.Position(diag.End) - if !end.IsValid() { - end = posn - } - data, _ := os.ReadFile(posn.Filename) - lines := strings.Split(string(data), "\n") - for i := posn.Line - contextLines; i <= end.Line+contextLines; i++ { - if 1 <= i && i <= len(lines) { - fmt.Fprintf(out, "%d\t%s\n", i, lines[i-1]) + print := func(pos, end token.Pos, message string) { + posn := fset.Position(pos) + fmt.Fprintf(out, "%s: %s\n", posn, message) + + // show offending line plus N lines of context. + if contextLines >= 0 { + end := fset.Position(end) + if !end.IsValid() { + end = posn + } + // TODO(adonovan): highlight the portion of the line indicated + // by pos...end using ASCII art, terminal colors, etc? + data, _ := os.ReadFile(posn.Filename) + lines := strings.Split(string(data), "\n") + for i := posn.Line - contextLines; i <= end.Line+contextLines; i++ { + if 1 <= i && i <= len(lines) { + fmt.Fprintf(out, "%d\t%s\n", i, lines[i-1]) + } } } } + + print(diag.Pos, diag.End, diag.Message) + for _, rel := range diag.Related { + print(rel.Pos, rel.End, "\t"+rel.Message) + } } // A JSONTree is a mapping from package ID to analysis name to result. diff --git a/vendor/golang.org/x/tools/go/ast/inspector/inspector.go b/vendor/golang.org/x/tools/go/ast/inspector/inspector.go index bc44b2c8e..a703cdfcf 100644 --- a/vendor/golang.org/x/tools/go/ast/inspector/inspector.go +++ b/vendor/golang.org/x/tools/go/ast/inspector/inspector.go @@ -85,6 +85,7 @@ type event struct { // TODO: Experiment with storing only the second word of event.node (unsafe.Pointer). // Type can be recovered from the sole bit in typ. +// [Tried this, wasn't faster. --adonovan] // Preorder visits all the nodes of the files supplied to New in // depth-first order. It calls f(n) for each node n before it visits diff --git a/vendor/golang.org/x/tools/go/ast/inspector/typeof.go b/vendor/golang.org/x/tools/go/ast/inspector/typeof.go index be0f990a2..9852331a3 100644 --- a/vendor/golang.org/x/tools/go/ast/inspector/typeof.go +++ b/vendor/golang.org/x/tools/go/ast/inspector/typeof.go @@ -12,8 +12,6 @@ package inspector import ( "go/ast" "math" - - _ "unsafe" ) const ( diff --git a/vendor/golang.org/x/tools/go/packages/doc.go b/vendor/golang.org/x/tools/go/packages/doc.go index f1931d10e..366aab6b2 100644 --- a/vendor/golang.org/x/tools/go/packages/doc.go +++ b/vendor/golang.org/x/tools/go/packages/doc.go @@ -76,6 +76,8 @@ uninterpreted to Load, so that it can interpret them according to the conventions of the underlying build system. See the Example function for typical usage. +See also [golang.org/x/tools/go/packages/internal/linecount] +for an example application. # The driver protocol diff --git a/vendor/golang.org/x/tools/internal/diff/lcs/doc.go b/vendor/golang.org/x/tools/internal/diff/lcs/doc.go index 9029dd20b..aa4b0fb59 100644 --- a/vendor/golang.org/x/tools/internal/diff/lcs/doc.go +++ b/vendor/golang.org/x/tools/internal/diff/lcs/doc.go @@ -139,7 +139,7 @@ computed labels. That is the worst case. Had the code noticed (x,y)=(u,v)=(3,3) from the edgegraph. The implementation looks for a number of special cases to try to avoid computing an extra forward path. If the two-sided algorithm has stop early (because D has become too large) it will have found a forward LCS and a -backwards LCS. Ideally these go with disjoint prefixes and suffixes of A and B, but disjointness may fail and the two +backwards LCS. Ideally these go with disjoint prefixes and suffixes of A and B, but disjointedness may fail and the two computed LCS may conflict. (An easy example is where A is a suffix of B, and shares a short prefix. The backwards LCS is all of A, and the forward LCS is a prefix of A.) The algorithm combines the two to form a best-effort LCS. In the worst case the forward partial LCS may have to diff --git a/vendor/modules.txt b/vendor/modules.txt index 6f2b90446..3b890382f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -109,8 +109,8 @@ github.com/chai2010/gettext-go/po # github.com/containerd/cgroups/v3 v3.0.5 ## explicit; go 1.22.0 github.com/containerd/cgroups/v3/cgroup1/stats -# github.com/containerd/containerd v1.7.27 -## explicit; go 1.21 +# github.com/containerd/containerd v1.7.28 +## explicit; go 1.23.0 github.com/containerd/containerd/archive github.com/containerd/containerd/archive/compression github.com/containerd/containerd/archive/tarheader @@ -187,7 +187,7 @@ github.com/containers/common/pkg/auth github.com/containers/common/pkg/capabilities github.com/containers/common/pkg/completion github.com/containers/common/pkg/password -# github.com/containers/image/v5 v5.36.0 +# github.com/containers/image/v5 v5.36.1 ## explicit; go 1.23.3 github.com/containers/image/v5/copy github.com/containers/image/v5/directory/explicitfilepath @@ -261,7 +261,7 @@ github.com/containers/ocicrypt/keywrap/pkcs7 github.com/containers/ocicrypt/spec github.com/containers/ocicrypt/utils github.com/containers/ocicrypt/utils/keyprovider -# github.com/containers/storage v1.59.0 +# github.com/containers/storage v1.59.1 ## explicit; go 1.23.0 github.com/containers/storage/internal/rawfilelock github.com/containers/storage/pkg/archive @@ -305,7 +305,7 @@ github.com/docker/cli/cli/config/types github.com/docker/distribution/registry/api/errcode github.com/docker/distribution/registry/api/v2 github.com/docker/distribution/registry/client/auth/challenge -# github.com/docker/docker v28.3.2+incompatible +# github.com/docker/docker v28.3.3+incompatible ## explicit github.com/docker/docker/api/types/versions # github.com/docker/docker-credential-helpers v0.9.3 @@ -405,8 +405,8 @@ github.com/gobwas/glob/util/strings ## explicit; go 1.15 github.com/gogo/protobuf/proto github.com/gogo/protobuf/sortkeys -# github.com/golang-jwt/jwt/v5 v5.2.3 -## explicit; go 1.18 +# github.com/golang-jwt/jwt/v5 v5.3.0 +## explicit; go 1.21 github.com/golang-jwt/jwt/v5 # github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 ## explicit; go 1.20 @@ -417,7 +417,7 @@ github.com/golang/protobuf/proto # github.com/google/btree v1.1.3 ## explicit; go 1.18 github.com/google/btree -# github.com/google/cel-go v0.25.0 +# github.com/google/cel-go v0.26.0 ## explicit; go 1.22.0 github.com/google/cel-go/cel github.com/google/cel-go/checker @@ -684,8 +684,8 @@ github.com/opencontainers/image-spec/specs-go/v1 # github.com/opencontainers/runtime-spec v1.2.1 ## explicit github.com/opencontainers/runtime-spec/specs-go -# github.com/operator-framework/api v0.32.0 -## explicit; go 1.24.3 +# github.com/operator-framework/api v0.33.0 +## explicit; go 1.24.4 github.com/operator-framework/api/pkg/constraints github.com/operator-framework/api/pkg/encoding github.com/operator-framework/api/pkg/lib/version @@ -743,8 +743,10 @@ github.com/pmezard/go-difflib/difflib # github.com/proglottis/gpgme v0.1.4 ## explicit; go 1.17 github.com/proglottis/gpgme -# github.com/prometheus/client_golang v1.22.0 -## explicit; go 1.22 +# github.com/prometheus/client_golang v1.23.0 +## explicit; go 1.23.0 +github.com/prometheus/client_golang/api +github.com/prometheus/client_golang/api/prometheus/v1 github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil/header github.com/prometheus/client_golang/prometheus @@ -937,7 +939,7 @@ go.yaml.in/yaml/v2 # go.yaml.in/yaml/v3 v3.0.3 ## explicit; go 1.22 go.yaml.in/yaml/v3 -# golang.org/x/crypto v0.40.0 +# golang.org/x/crypto v0.41.0 ## explicit; go 1.23.0 golang.org/x/crypto/bcrypt golang.org/x/crypto/blowfish @@ -963,13 +965,13 @@ golang.org/x/crypto/sha3 ## explicit; go 1.23.0 golang.org/x/exp/maps golang.org/x/exp/slices -# golang.org/x/mod v0.26.0 +# golang.org/x/mod v0.27.0 ## explicit; go 1.23.0 golang.org/x/mod/internal/lazyregexp golang.org/x/mod/modfile golang.org/x/mod/module golang.org/x/mod/semver -# golang.org/x/net v0.42.0 +# golang.org/x/net v0.43.0 ## explicit; go 1.23.0 golang.org/x/net/context golang.org/x/net/html @@ -993,17 +995,17 @@ golang.org/x/oauth2/internal golang.org/x/sync/errgroup golang.org/x/sync/semaphore golang.org/x/sync/singleflight -# golang.org/x/sys v0.34.0 +# golang.org/x/sys v0.35.0 ## explicit; go 1.23.0 golang.org/x/sys/cpu golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows golang.org/x/sys/windows/registry -# golang.org/x/term v0.33.0 +# golang.org/x/term v0.34.0 ## explicit; go 1.23.0 golang.org/x/term -# golang.org/x/text v0.27.0 +# golang.org/x/text v0.28.0 ## explicit; go 1.23.0 golang.org/x/text/cases golang.org/x/text/encoding @@ -1031,7 +1033,7 @@ golang.org/x/text/unicode/norm # golang.org/x/time v0.12.0 ## explicit; go 1.23.0 golang.org/x/time/rate -# golang.org/x/tools v0.35.0 +# golang.org/x/tools v0.36.0 ## explicit; go 1.23.0 golang.org/x/tools/go/analysis golang.org/x/tools/go/analysis/analysistest @@ -2107,7 +2109,7 @@ sigs.k8s.io/structured-merge-diff/v4/merge sigs.k8s.io/structured-merge-diff/v4/schema sigs.k8s.io/structured-merge-diff/v4/typed sigs.k8s.io/structured-merge-diff/v4/value -# sigs.k8s.io/yaml v1.5.0 +# sigs.k8s.io/yaml v1.6.0 ## explicit; go 1.22 sigs.k8s.io/yaml sigs.k8s.io/yaml/goyaml.v2