diff --git a/.golangci.yaml b/.golangci.yaml
index 76c007d9f4..ad93cf67f1 100644
--- a/.golangci.yaml
+++ b/.golangci.yaml
@@ -34,6 +34,8 @@ linters:
- nlreturn
# Replaced by whitespace.
- wsl
+ # We do not enforce godoc comments.
+ - godoclint
# https://golangci-lint.run/usage/linters/
enable:
- asasalint
@@ -107,6 +109,14 @@ linters:
text: 'G301: Expect directory permissions to be 0750 or less'
- path: 'pkg/components/storage\.go'
text: 'G302: Expect file permissions to be 0600 or less'
+ - path: 'pkg/config/node\.go'
+ text: 'G703: Path traversal via taint analysis'
+ - path: 'pkg/controllers/kube-apiserver\.go'
+ text: 'G703: Path traversal via taint analysis'
+ - path: 'pkg/telemetry/telemetry\.go'
+ text: 'G704: SSRF via taint analysis'
+ - path: 'pkg/util/cryptomaterial/certchains/signers\.go'
+ text: 'toBuilder returns interface'
settings:
cyclop:
max-complexity: 20
diff --git a/Makefile b/Makefile
index 286560609e..0286fef873 100644
--- a/Makefile
+++ b/Makefile
@@ -104,7 +104,7 @@ GO_TEST_PACKAGES=./cmd/... ./pkg/...
export CGO_ENABLED ?= 1
# Specify OCP build tools image tag when building rpm with podman
-RPM_BUILDER_IMAGE_TAG := rhel-9-golang-1.24-openshift-4.20
+RPM_BUILDER_IMAGE_TAG := rhel-9-golang-1.25-openshift-4.22
all: generate-config microshift etcd
diff --git a/Makefile.kube_git.var b/Makefile.kube_git.var
index 2871ba4ea2..677e48a233 100644
--- a/Makefile.kube_git.var
+++ b/Makefile.kube_git.var
@@ -1,5 +1,5 @@
KUBE_GIT_MAJOR=1
KUBE_GIT_MINOR=34
KUBE_GIT_VERSION=v1.34.2
-KUBE_GIT_COMMIT=9d521311f5fb67dc43f49eeb728ee2c80976835a
+KUBE_GIT_COMMIT=047d96223dd843e9d54bed59bc212d2e9122c56a
KUBE_GIT_TREE_STATE=clean
diff --git a/Makefile.version.aarch64.var b/Makefile.version.aarch64.var
index 397442990f..3ffad689b4 100644
--- a/Makefile.version.aarch64.var
+++ b/Makefile.version.aarch64.var
@@ -1 +1 @@
-OCP_VERSION := 4.22.0-0.nightly-arm64-2026-02-05-082424
+OCP_VERSION := 4.22.0-0.nightly-arm64-2026-02-17-232712
diff --git a/Makefile.version.x86_64.var b/Makefile.version.x86_64.var
index d15390635b..77d5443753 100644
--- a/Makefile.version.x86_64.var
+++ b/Makefile.version.x86_64.var
@@ -1 +1 @@
-OCP_VERSION := 4.22.0-0.nightly-2026-02-05-115400
+OCP_VERSION := 4.22.0-0.nightly-2026-02-17-112443
diff --git a/assets/components/multus/kustomization.aarch64.yaml b/assets/components/multus/kustomization.aarch64.yaml
index c9ff38bd61..6e974bed3b 100644
--- a/assets/components/multus/kustomization.aarch64.yaml
+++ b/assets/components/multus/kustomization.aarch64.yaml
@@ -2,7 +2,7 @@
images:
- name: multus-cni-microshift
newName: quay.io/openshift-release-dev/ocp-v4.0-art-dev
- digest: sha256:18382b50036fed824eaa818406de54f31a19d506d84ba69076647709c0bebd0c
+ digest: sha256:5059097d17fbc06dbe7a9e7f0d61116eeb2750fcc2debc54842916cc35181a06
- name: containernetworking-plugins-microshift
newName: quay.io/openshift-release-dev/ocp-v4.0-art-dev
- digest: sha256:476c31c3adc585ec503b0717bc8898fdaa0d5c51d4ad3acf80acfb8140cc182f
+ digest: sha256:267c37338b0fddc68fd1b7657c722ee0238675ef85b0f274e69fdf96d9df26c6
diff --git a/assets/components/multus/kustomization.x86_64.yaml b/assets/components/multus/kustomization.x86_64.yaml
index e1c7209f25..09d51e153e 100644
--- a/assets/components/multus/kustomization.x86_64.yaml
+++ b/assets/components/multus/kustomization.x86_64.yaml
@@ -2,7 +2,7 @@
images:
- name: multus-cni-microshift
newName: quay.io/openshift-release-dev/ocp-v4.0-art-dev
- digest: sha256:0db85138bfe4a129e0b85a203ca0c8400145d8fa2e234c467d8496d89a0e66fb
+ digest: sha256:e9b425020d10f9f7ab0ddf27b082dd69e7b5c97f498608f9761f88b533d593d8
- name: containernetworking-plugins-microshift
newName: quay.io/openshift-release-dev/ocp-v4.0-art-dev
- digest: sha256:31264e37769680f66240b51d02b4cbcf12565a9d0ce961a7c23bf90e9e463a99
+ digest: sha256:474aa143fb27219d5be46488f70a56e0fdf25864276fbcfd48c64d10329ab341
diff --git a/assets/components/multus/release-multus-aarch64.json b/assets/components/multus/release-multus-aarch64.json
index fb03d56263..2a9f76bdc9 100644
--- a/assets/components/multus/release-multus-aarch64.json
+++ b/assets/components/multus/release-multus-aarch64.json
@@ -1,9 +1,9 @@
{
"release": {
- "base": "4.22.0-0.nightly-arm64-2026-02-05-082424"
+ "base": "4.22.0-0.nightly-arm64-2026-02-17-232712"
},
"images": {
- "multus-cni-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:18382b50036fed824eaa818406de54f31a19d506d84ba69076647709c0bebd0c",
- "containernetworking-plugins-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:476c31c3adc585ec503b0717bc8898fdaa0d5c51d4ad3acf80acfb8140cc182f"
+ "multus-cni-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:5059097d17fbc06dbe7a9e7f0d61116eeb2750fcc2debc54842916cc35181a06",
+ "containernetworking-plugins-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:267c37338b0fddc68fd1b7657c722ee0238675ef85b0f274e69fdf96d9df26c6"
}
}
diff --git a/assets/components/multus/release-multus-x86_64.json b/assets/components/multus/release-multus-x86_64.json
index 7d6e4c9f96..b80bb25ebc 100644
--- a/assets/components/multus/release-multus-x86_64.json
+++ b/assets/components/multus/release-multus-x86_64.json
@@ -1,9 +1,9 @@
{
"release": {
- "base": "4.22.0-0.nightly-2026-02-05-115400"
+ "base": "4.22.0-0.nightly-2026-02-17-112443"
},
"images": {
- "multus-cni-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:0db85138bfe4a129e0b85a203ca0c8400145d8fa2e234c467d8496d89a0e66fb",
- "containernetworking-plugins-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:31264e37769680f66240b51d02b4cbcf12565a9d0ce961a7c23bf90e9e463a99"
+ "multus-cni-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:e9b425020d10f9f7ab0ddf27b082dd69e7b5c97f498608f9761f88b533d593d8",
+ "containernetworking-plugins-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:474aa143fb27219d5be46488f70a56e0fdf25864276fbcfd48c64d10329ab341"
}
}
diff --git a/assets/components/openshift-dns/dns/service.yaml b/assets/components/openshift-dns/dns/service.yaml
index 3849d98bce..a53188dcc6 100644
--- a/assets/components/openshift-dns/dns/service.yaml
+++ b/assets/components/openshift-dns/dns/service.yaml
@@ -1,6 +1,7 @@
kind: Service
apiVersion: v1
spec:
+ trafficDistribution: PreferSameNode
ports:
- name: dns
port: 53
diff --git a/assets/optional/operator-lifecycle-manager/0000_50_olm_00-catalogsources.crd.yaml b/assets/optional/operator-lifecycle-manager/0000_50_olm_00-catalogsources.crd.yaml
index e0bde39811..d0455ae902 100644
--- a/assets/optional/operator-lifecycle-manager/0000_50_olm_00-catalogsources.crd.yaml
+++ b/assets/optional/operator-lifecycle-manager/0000_50_olm_00-catalogsources.crd.yaml
@@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.19.0
+ controller-gen.kubebuilder.io/version: v0.20.0
include.release.openshift.io/ibm-cloud-managed: "true"
include.release.openshift.io/self-managed-high-availability: "true"
capability.openshift.io/name: "OperatorLifecycleManager"
@@ -1049,9 +1049,10 @@ spec:
operator:
description: |-
Operator represents a key's relationship to the value.
- Valid operators are Exists and Equal. Defaults to Equal.
+ Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal.
Exists is equivalent to wildcard for value, so that a pod can
tolerate all taints of a particular category.
+ Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators).
type: string
tolerationSeconds:
description: |-
diff --git a/assets/optional/operator-lifecycle-manager/0000_50_olm_00-clusterserviceversions.crd.yaml b/assets/optional/operator-lifecycle-manager/0000_50_olm_00-clusterserviceversions.crd.yaml
index b2ed5a0f71..b3ffad4856 100644
--- a/assets/optional/operator-lifecycle-manager/0000_50_olm_00-clusterserviceversions.crd.yaml
+++ b/assets/optional/operator-lifecycle-manager/0000_50_olm_00-clusterserviceversions.crd.yaml
@@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.19.0
+ controller-gen.kubebuilder.io/version: v0.20.0
include.release.openshift.io/ibm-cloud-managed: "true"
include.release.openshift.io/self-managed-high-availability: "true"
capability.openshift.io/name: "OperatorLifecycleManager"
@@ -2560,7 +2560,9 @@ spec:
type: integer
format: int32
resizePolicy:
- description: Resources resize policy for the container.
+ description: |-
+ Resources resize policy for the container.
+ This field cannot be set on ephemeral containers.
type: array
items:
description: ContainerResizePolicy represents resource resize policy for the container.
@@ -5633,7 +5635,9 @@ spec:
type: integer
format: int32
resizePolicy:
- description: Resources resize policy for the container.
+ description: |-
+ Resources resize policy for the container.
+ This field cannot be set on ephemeral containers.
type: array
items:
description: ContainerResizePolicy represents resource resize policy for the container.
@@ -6390,8 +6394,8 @@ spec:
will be made available to those containers which consume them
by name.
- This is an alpha field and requires enabling the
- DynamicResourceAllocation feature gate.
+ This is a stable field but requires that the
+ DynamicResourceAllocation feature gate is enabled.
This field is immutable.
type: array
@@ -6845,9 +6849,10 @@ spec:
operator:
description: |-
Operator represents a key's relationship to the value.
- Valid operators are Exists and Equal. Defaults to Equal.
+ Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal.
Exists is equivalent to wildcard for value, so that a pod can
tolerate all taints of a particular category.
+ Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators).
type: string
tolerationSeconds:
description: |-
@@ -7609,7 +7614,7 @@ spec:
resources:
description: |-
resources represents the minimum resources the volume should have.
- If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements
+ Users are allowed to specify resource requirements
that are lower than previous value but must still be higher than capacity recorded in the
status field of the claim.
More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources
@@ -8446,6 +8451,24 @@ spec:
signerName:
description: Kubelet's generated CSRs will be addressed to this signer.
type: string
+ userAnnotations:
+ description: |-
+ userAnnotations allow pod authors to pass additional information to
+ the signer implementation. Kubernetes does not restrict or validate this
+ metadata in any way.
+
+ These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of
+ the PodCertificateRequest objects that Kubelet creates.
+
+ Entries are subject to the same validation as object metadata annotations,
+ with the addition that all keys must be domain-prefixed. No restrictions
+ are placed on values, except an overall size limitation on the entire field.
+
+ Signers should document the keys and values they support. Signers should
+ deny requests that contain keys they do not recognize.
+ type: object
+ additionalProperties:
+ type: string
secret:
description: secret information about the secret data to project
type: object
@@ -8844,6 +8867,42 @@ spec:
x-kubernetes-list-map-keys:
- name
x-kubernetes-list-type: map
+ workloadRef:
+ description: |-
+ WorkloadRef provides a reference to the Workload object that this Pod belongs to.
+ This field is used by the scheduler to identify the PodGroup and apply the
+ correct group scheduling policies. The Workload object referenced
+ by this field may not exist at the time the Pod is created.
+ This field is immutable, but a Workload object with the same name
+ may be recreated with different policies. Doing this during pod scheduling
+ may result in the placement not conforming to the expected policies.
+ type: object
+ required:
+ - name
+ - podGroup
+ properties:
+ name:
+ description: |-
+ Name defines the name of the Workload object this Pod belongs to.
+ Workload must be in the same namespace as the Pod.
+ If it doesn't match any existing Workload, the Pod will remain unschedulable
+ until a Workload object is created and observed by the kube-scheduler.
+ It must be a DNS subdomain.
+ type: string
+ podGroup:
+ description: |-
+ PodGroup is the name of the PodGroup within the Workload that this Pod
+ belongs to. If it doesn't match any existing PodGroup within the Workload,
+ the Pod will remain unschedulable until the Workload object is recreated
+ and observed by the kube-scheduler. It must be a DNS label.
+ type: string
+ podGroupReplicaKey:
+ description: |-
+ PodGroupReplicaKey specifies the replica key of the PodGroup to which this
+ Pod belongs. It is used to distinguish pods belonging to different replicas
+ of the same pod group. The pod group policy is applied separately to each replica.
+ When set, it must be a DNS label.
+ type: string
permissions:
type: array
items:
@@ -9159,7 +9218,9 @@ spec:
type: string
x-kubernetes-map-type: atomic
reinvocationPolicy:
- description: ReinvocationPolicyType specifies what type of policy the admission hook uses.
+ description: |-
+ ReinvocationPolicyType specifies what type of policy is used when other admission plugins also perform
+ modifications.
type: string
rules:
type: array
diff --git a/assets/optional/operator-lifecycle-manager/0000_50_olm_00-installplans.crd.yaml b/assets/optional/operator-lifecycle-manager/0000_50_olm_00-installplans.crd.yaml
index 08f6701336..6f3936c69e 100644
--- a/assets/optional/operator-lifecycle-manager/0000_50_olm_00-installplans.crd.yaml
+++ b/assets/optional/operator-lifecycle-manager/0000_50_olm_00-installplans.crd.yaml
@@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.19.0
+ controller-gen.kubebuilder.io/version: v0.20.0
include.release.openshift.io/ibm-cloud-managed: "true"
include.release.openshift.io/self-managed-high-availability: "true"
capability.openshift.io/name: "OperatorLifecycleManager"
diff --git a/assets/optional/operator-lifecycle-manager/0000_50_olm_00-olmconfigs.crd.yaml b/assets/optional/operator-lifecycle-manager/0000_50_olm_00-olmconfigs.crd.yaml
index ec2291246b..90af18a959 100644
--- a/assets/optional/operator-lifecycle-manager/0000_50_olm_00-olmconfigs.crd.yaml
+++ b/assets/optional/operator-lifecycle-manager/0000_50_olm_00-olmconfigs.crd.yaml
@@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.19.0
+ controller-gen.kubebuilder.io/version: v0.20.0
include.release.openshift.io/ibm-cloud-managed: "true"
include.release.openshift.io/self-managed-high-availability: "true"
capability.openshift.io/name: "OperatorLifecycleManager"
diff --git a/assets/optional/operator-lifecycle-manager/0000_50_olm_00-operatorconditions.crd.yaml b/assets/optional/operator-lifecycle-manager/0000_50_olm_00-operatorconditions.crd.yaml
index 2f5a208669..797a47b740 100644
--- a/assets/optional/operator-lifecycle-manager/0000_50_olm_00-operatorconditions.crd.yaml
+++ b/assets/optional/operator-lifecycle-manager/0000_50_olm_00-operatorconditions.crd.yaml
@@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.19.0
+ controller-gen.kubebuilder.io/version: v0.20.0
include.release.openshift.io/ibm-cloud-managed: "true"
include.release.openshift.io/self-managed-high-availability: "true"
capability.openshift.io/name: "OperatorLifecycleManager"
diff --git a/assets/optional/operator-lifecycle-manager/0000_50_olm_00-operatorgroups.crd.yaml b/assets/optional/operator-lifecycle-manager/0000_50_olm_00-operatorgroups.crd.yaml
index acf2160ddc..1409d8aa27 100644
--- a/assets/optional/operator-lifecycle-manager/0000_50_olm_00-operatorgroups.crd.yaml
+++ b/assets/optional/operator-lifecycle-manager/0000_50_olm_00-operatorgroups.crd.yaml
@@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.19.0
+ controller-gen.kubebuilder.io/version: v0.20.0
include.release.openshift.io/ibm-cloud-managed: "true"
include.release.openshift.io/self-managed-high-availability: "true"
capability.openshift.io/name: "OperatorLifecycleManager"
diff --git a/assets/optional/operator-lifecycle-manager/0000_50_olm_00-operators.crd.yaml b/assets/optional/operator-lifecycle-manager/0000_50_olm_00-operators.crd.yaml
index c571a3264a..f1c29977d1 100644
--- a/assets/optional/operator-lifecycle-manager/0000_50_olm_00-operators.crd.yaml
+++ b/assets/optional/operator-lifecycle-manager/0000_50_olm_00-operators.crd.yaml
@@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.19.0
+ controller-gen.kubebuilder.io/version: v0.20.0
include.release.openshift.io/ibm-cloud-managed: "true"
include.release.openshift.io/self-managed-high-availability: "true"
capability.openshift.io/name: "OperatorLifecycleManager"
diff --git a/assets/optional/operator-lifecycle-manager/0000_50_olm_00-subscriptions.crd.yaml b/assets/optional/operator-lifecycle-manager/0000_50_olm_00-subscriptions.crd.yaml
index 87ce80f720..790b096871 100644
--- a/assets/optional/operator-lifecycle-manager/0000_50_olm_00-subscriptions.crd.yaml
+++ b/assets/optional/operator-lifecycle-manager/0000_50_olm_00-subscriptions.crd.yaml
@@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
- controller-gen.kubebuilder.io/version: v0.19.0
+ controller-gen.kubebuilder.io/version: v0.20.0
include.release.openshift.io/ibm-cloud-managed: "true"
include.release.openshift.io/self-managed-high-availability: "true"
capability.openshift.io/name: "OperatorLifecycleManager"
@@ -1301,9 +1301,10 @@ spec:
operator:
description: |-
Operator represents a key's relationship to the value.
- Valid operators are Exists and Equal. Defaults to Equal.
+ Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal.
Exists is equivalent to wildcard for value, so that a pod can
tolerate all taints of a particular category.
+ Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators).
type: string
tolerationSeconds:
description: |-
@@ -1947,7 +1948,7 @@ spec:
resources:
description: |-
resources represents the minimum resources the volume should have.
- If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements
+ Users are allowed to specify resource requirements
that are lower than previous value but must still be higher than capacity recorded in the
status field of the claim.
More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources
@@ -2784,6 +2785,24 @@ spec:
signerName:
description: Kubelet's generated CSRs will be addressed to this signer.
type: string
+ userAnnotations:
+ description: |-
+ userAnnotations allow pod authors to pass additional information to
+ the signer implementation. Kubernetes does not restrict or validate this
+ metadata in any way.
+
+ These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of
+ the PodCertificateRequest objects that Kubelet creates.
+
+ Entries are subject to the same validation as object metadata annotations,
+ with the addition that all keys must be domain-prefixed. No restrictions
+ are placed on values, except an overall size limitation on the entire field.
+
+ Signers should document the keys and values they support. Signers should
+ deny requests that contain keys they do not recognize.
+ type: object
+ additionalProperties:
+ type: string
secret:
description: secret information about the secret data to project
type: object
diff --git a/assets/optional/operator-lifecycle-manager/kustomization.aarch64.yaml b/assets/optional/operator-lifecycle-manager/kustomization.aarch64.yaml
index 09a54125de..07c1d2efaa 100644
--- a/assets/optional/operator-lifecycle-manager/kustomization.aarch64.yaml
+++ b/assets/optional/operator-lifecycle-manager/kustomization.aarch64.yaml
@@ -2,13 +2,13 @@
images:
- name: quay.io/operator-framework/olm
newName: quay.io/openshift-release-dev/ocp-v4.0-art-dev
- digest: sha256:9d3d8d0887ab9d994634f902885f362e1140cc206e47198d1ca593a60fc6f161
+ digest: sha256:9cae71a754b76203d01e23ec9c6730c1ce9be6c37a7451243d27bf419ceaddd8
- name: quay.io/operator-framework/configmap-operator-registry
newName: quay.io/openshift-release-dev/ocp-v4.0-art-dev
- digest: sha256:cdf1049fa246fa36a79e0e4d4baaf5c97a0576002218f2fc10b6448b9260e61f
+ digest: sha256:10632a362e40bcfb78e901778b63d17f1360a2564833ea3de832a14a8b8b82f5
- name: quay.io/openshift/origin-kube-rbac-proxy
newName: quay.io/openshift-release-dev/ocp-v4.0-art-dev
- digest: sha256:9393b7488ecc8616f74897f4b23f7f5aad1a3aa1201d231251ccb3a2036b9ef6
+ digest: sha256:6a446c1612ba15b607869bc616cb6c1b5ed7966141f3a344d10968806e430c8b
patches:
- patch: |-
@@ -16,12 +16,12 @@ patches:
path: /spec/template/spec/containers/0/env/-
value:
name: OPERATOR_REGISTRY_IMAGE
- value: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:cdf1049fa246fa36a79e0e4d4baaf5c97a0576002218f2fc10b6448b9260e61f
+ value: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:10632a362e40bcfb78e901778b63d17f1360a2564833ea3de832a14a8b8b82f5
- op: add
path: /spec/template/spec/containers/0/env/-
value:
name: OLM_IMAGE
- value: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9d3d8d0887ab9d994634f902885f362e1140cc206e47198d1ca593a60fc6f161
+ value: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9cae71a754b76203d01e23ec9c6730c1ce9be6c37a7451243d27bf419ceaddd8
target:
kind: Deployment
labelSelector: app=catalog-operator
diff --git a/assets/optional/operator-lifecycle-manager/kustomization.x86_64.yaml b/assets/optional/operator-lifecycle-manager/kustomization.x86_64.yaml
index 4e5adf9f40..af85db5586 100644
--- a/assets/optional/operator-lifecycle-manager/kustomization.x86_64.yaml
+++ b/assets/optional/operator-lifecycle-manager/kustomization.x86_64.yaml
@@ -2,13 +2,13 @@
images:
- name: quay.io/operator-framework/olm
newName: quay.io/openshift-release-dev/ocp-v4.0-art-dev
- digest: sha256:a7cf23b5d9ec933b8ae281acf568521ea54816c57baddcdeda1df3aa85171a02
+ digest: sha256:5cacff5077abbababa5336b6ebb334377382817184b8ce7cfda87b589544b4cc
- name: quay.io/operator-framework/configmap-operator-registry
newName: quay.io/openshift-release-dev/ocp-v4.0-art-dev
- digest: sha256:a2f2eaae95ddbd87b1c20a58edf725c515ccee4befe7aa78f69fefec2289f87f
+ digest: sha256:2469bfae8f97154da2cb84eb19f75fe7918c316a22240c29865d296f326c1914
- name: quay.io/openshift/origin-kube-rbac-proxy
newName: quay.io/openshift-release-dev/ocp-v4.0-art-dev
- digest: sha256:024a086dee9aed18b6e0348e728b06711853061962fe042a9f89b91f53d1bf8c
+ digest: sha256:74536a9ae64f64aa25dcd7ff3a529b2bddb76cef69847e6a4fbc5716b2f05a53
patches:
- patch: |-
@@ -16,12 +16,12 @@ patches:
path: /spec/template/spec/containers/0/env/-
value:
name: OPERATOR_REGISTRY_IMAGE
- value: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a2f2eaae95ddbd87b1c20a58edf725c515ccee4befe7aa78f69fefec2289f87f
+ value: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:2469bfae8f97154da2cb84eb19f75fe7918c316a22240c29865d296f326c1914
- op: add
path: /spec/template/spec/containers/0/env/-
value:
name: OLM_IMAGE
- value: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a7cf23b5d9ec933b8ae281acf568521ea54816c57baddcdeda1df3aa85171a02
+ value: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:5cacff5077abbababa5336b6ebb334377382817184b8ce7cfda87b589544b4cc
target:
kind: Deployment
labelSelector: app=catalog-operator
diff --git a/assets/optional/operator-lifecycle-manager/release-olm-aarch64.json b/assets/optional/operator-lifecycle-manager/release-olm-aarch64.json
index 60e8f87c36..45d6b3f6b4 100644
--- a/assets/optional/operator-lifecycle-manager/release-olm-aarch64.json
+++ b/assets/optional/operator-lifecycle-manager/release-olm-aarch64.json
@@ -1,10 +1,10 @@
{
"release": {
- "base": "4.22.0-0.nightly-arm64-2026-02-05-082424"
+ "base": "4.22.0-0.nightly-arm64-2026-02-17-232712"
},
"images": {
- "operator-lifecycle-manager": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9d3d8d0887ab9d994634f902885f362e1140cc206e47198d1ca593a60fc6f161",
- "operator-registry": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:cdf1049fa246fa36a79e0e4d4baaf5c97a0576002218f2fc10b6448b9260e61f",
- "kube-rbac-proxy": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9393b7488ecc8616f74897f4b23f7f5aad1a3aa1201d231251ccb3a2036b9ef6"
+ "operator-lifecycle-manager": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9cae71a754b76203d01e23ec9c6730c1ce9be6c37a7451243d27bf419ceaddd8",
+ "operator-registry": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:10632a362e40bcfb78e901778b63d17f1360a2564833ea3de832a14a8b8b82f5",
+ "kube-rbac-proxy": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:6a446c1612ba15b607869bc616cb6c1b5ed7966141f3a344d10968806e430c8b"
}
}
diff --git a/assets/optional/operator-lifecycle-manager/release-olm-x86_64.json b/assets/optional/operator-lifecycle-manager/release-olm-x86_64.json
index b7f0b6da1c..d46c015625 100644
--- a/assets/optional/operator-lifecycle-manager/release-olm-x86_64.json
+++ b/assets/optional/operator-lifecycle-manager/release-olm-x86_64.json
@@ -1,10 +1,10 @@
{
"release": {
- "base": "4.22.0-0.nightly-2026-02-05-115400"
+ "base": "4.22.0-0.nightly-2026-02-17-112443"
},
"images": {
- "operator-lifecycle-manager": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a7cf23b5d9ec933b8ae281acf568521ea54816c57baddcdeda1df3aa85171a02",
- "operator-registry": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a2f2eaae95ddbd87b1c20a58edf725c515ccee4befe7aa78f69fefec2289f87f",
- "kube-rbac-proxy": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:024a086dee9aed18b6e0348e728b06711853061962fe042a9f89b91f53d1bf8c"
+ "operator-lifecycle-manager": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:5cacff5077abbababa5336b6ebb334377382817184b8ce7cfda87b589544b4cc",
+ "operator-registry": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:2469bfae8f97154da2cb84eb19f75fe7918c316a22240c29865d296f326c1914",
+ "kube-rbac-proxy": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:74536a9ae64f64aa25dcd7ff3a529b2bddb76cef69847e6a4fbc5716b2f05a53"
}
}
diff --git a/assets/release/release-aarch64.json b/assets/release/release-aarch64.json
index 529ace6634..ba13b88eeb 100644
--- a/assets/release/release-aarch64.json
+++ b/assets/release/release-aarch64.json
@@ -1,16 +1,16 @@
{
"release": {
- "base": "4.22.0-0.nightly-arm64-2026-02-05-082424"
+ "base": "4.22.0-0.nightly-arm64-2026-02-17-232712"
},
"images": {
- "cli": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a6af2b68b2eec4026080790521abcd5b1ba599e59caf42d053f8a18d8bec09a7",
- "coredns": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:8ee3f8034bf2d07aefcb75b1ffe5c7222290f324aa7234895aa87e6bdd09e237",
- "haproxy-router": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:3436721bfc2a010877c4476e450e283820d7dd53777ed1be9a78b969a913f179",
- "kube-rbac-proxy": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9393b7488ecc8616f74897f4b23f7f5aad1a3aa1201d231251ccb3a2036b9ef6",
- "ovn-kubernetes-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f3b010cb1c627955c37942bbb35323f631ac4c827329d410a8f7f868d6998083",
- "pod": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:e95d5626e35158343ffe994f18588fb91a6baa7ce513b8a17e095d16e6b0293c",
- "service-ca-operator": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:774023f17193a125c5e6e8a6bba53ca21ea19c80e840a7110c94ba3f5c4ecb02",
+ "cli": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:b3942ad8c93f5222836244549cbad53c745f3b16699824319f2a020257457703",
+ "coredns": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:8a5d616c836eafa3dd9f7f56bc8592d8077486da4a08064a473ef8e34a8be2e9",
+ "haproxy-router": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:73921004aa9c53caddc8fda86f36ad0cf857943be302c4389f12e13601bd8113",
+ "kube-rbac-proxy": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:6a446c1612ba15b607869bc616cb6c1b5ed7966141f3a344d10968806e430c8b",
+ "ovn-kubernetes-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a3133d0ca6104900cb738b95305a23ccb3f675a1d60ad6a49d90379a724477fc",
+ "pod": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f119f20eded8102499fb9a65a990d7e3e8e47f866efe70db6597718dd2a42b20",
+ "service-ca-operator": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f1a1f77684c7ce10cbbf0dc9d434dfe4930fa43badd03643075e3c00dedda93c",
"lvms_operator": "registry.redhat.io/lvms4/lvms-rhel9-operator@sha256:3766640b19c336b443619ecdb35f36b479c79ea71b21de97febf024a5eaf6c84",
- "csi-snapshot-controller": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:fca9e70ea3d71025d969a5e14fc0272f4bd0c25012db2bd86f5fd5e5bd917d7d"
+ "csi-snapshot-controller": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:536d16747670ce324de4dbb9f4bf7a3ee5871e6b70dc2639fbf2a1397bc4a329"
}
}
diff --git a/assets/release/release-x86_64.json b/assets/release/release-x86_64.json
index 148cea3c68..27f79e34c9 100644
--- a/assets/release/release-x86_64.json
+++ b/assets/release/release-x86_64.json
@@ -1,16 +1,16 @@
{
"release": {
- "base": "4.22.0-0.nightly-2026-02-05-115400"
+ "base": "4.22.0-0.nightly-2026-02-17-112443"
},
"images": {
- "cli": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:191385c8b2fdab6b1bdbbf8bc7eca917d70e5e8d60019f304de6c46fbdcccf6d",
- "coredns": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:1d83a353d3f75275640cc6b9c613d8d8eb99f18e4b8ffa79b83728b7dfbecaca",
- "haproxy-router": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:3c9ef4de05d8cfe9799f9134856dca64adb00fb2d8757ae4fcf42f6abefecec8",
- "kube-rbac-proxy": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:024a086dee9aed18b6e0348e728b06711853061962fe042a9f89b91f53d1bf8c",
- "ovn-kubernetes-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:02a5485f93b3c117a165caf5057886cc30bf11ba4fa2a8250c21b4694ae4c9ab",
- "pod": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:89d38d074f3fefeafe47171f755345c5ef521324af0f32683bf9a69068ee6d90",
- "service-ca-operator": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:47e2e3c31c7955bafff142e64fb4810a02d40ed6d8e63552410cce04ed1484a2",
+ "cli": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:12fcf0dfc2aef1d52a1a211a0edfb5a4d7f1992de99c84d6ee112c2ced50b1b6",
+ "coredns": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9060aa9a30b0ec7a2f99e40278fbf0f3a82b9371b256615604b9cfb019d89891",
+ "haproxy-router": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:d87740f4ff9ed6ead0e9af1ea0c9a58fd28676a3931eae9be1067409a84e7704",
+ "kube-rbac-proxy": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:74536a9ae64f64aa25dcd7ff3a529b2bddb76cef69847e6a4fbc5716b2f05a53",
+ "ovn-kubernetes-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:13229c22b269d9eeab4a94ed138813043a7c894453fe21e1366962c4f6a40293",
+ "pod": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:7513507ca94673ee17e2bde9edd2335b8bea7a72ac17a32ba0d60808742b7527",
+ "service-ca-operator": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9b2bcab31455a22c66cbd0c8d67ea55f14fe7833f9ea2553d05ecdec76591f76",
"lvms_operator": "registry.redhat.io/lvms4/lvms-rhel9-operator@sha256:58804d8baf922927b66cec9424d431a3bdb341d207024ce40cc8f0123bac03ee",
- "csi-snapshot-controller": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f390128b70d502c35ae3f34f0acc6a57398ebf9d17490a83bc2bc942f75cf88a"
+ "csi-snapshot-controller": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:364ab6bc32abe7c7ad3558a26456dfe3064391768bc6dbfe12b0b10471fc0300"
}
}
diff --git a/cmd/generate-config/util.go b/cmd/generate-config/util.go
index 3d8e9b7dd0..2a8ed77ecb 100644
--- a/cmd/generate-config/util.go
+++ b/cmd/generate-config/util.go
@@ -145,7 +145,7 @@ func parseJSONValue(jsonType interface{}) (value string, node []*yaml.Node) {
}
func schemaKeyToOrderedArray[K string | int, V any](schemaProperties map[K]V) []K {
- var ordered = []K{}
+ var ordered = make([]K, 0, len(schemaProperties))
for k := range schemaProperties {
ordered = append(ordered, k)
}
diff --git a/deps/github.com/openshift/kubernetes/pkg/controller/volume/selinuxwarning/cache/volumecache.go b/deps/github.com/openshift/kubernetes/pkg/controller/volume/selinuxwarning/cache/volumecache.go
index dfa129dae9..4b19c985c8 100644
--- a/deps/github.com/openshift/kubernetes/pkg/controller/volume/selinuxwarning/cache/volumecache.go
+++ b/deps/github.com/openshift/kubernetes/pkg/controller/volume/selinuxwarning/cache/volumecache.go
@@ -114,11 +114,19 @@ func (c *volumeCache) AddVolume(logger klog.Logger, volumeName v1.UniqueVolumeNa
}
// The volume is already known
- // Add the pod to the cache or update its properties
- volume.pods[podKey] = podInfo{
+ podInfo := podInfo{
seLinuxLabel: label,
changePolicy: changePolicy,
}
+ oldPodInfo, found := volume.pods[podKey]
+ if found && oldPodInfo == podInfo {
+ // The Pod is already known too and nothing changed since the last update.
+ // All conflicts were already reported when the Pod was added / updated in the cache last time.
+ return conflicts
+ }
+
+ // Add the updated pod info to the cache
+ volume.pods[podKey] = podInfo
// Emit conflicts for the pod
for otherPodKey, otherPodInfo := range volume.pods {
diff --git a/deps/github.com/openshift/kubernetes/pkg/controller/volume/selinuxwarning/selinux_warning_controller.go b/deps/github.com/openshift/kubernetes/pkg/controller/volume/selinuxwarning/selinux_warning_controller.go
index e5049e05ab..d373eeabf5 100644
--- a/deps/github.com/openshift/kubernetes/pkg/controller/volume/selinuxwarning/selinux_warning_controller.go
+++ b/deps/github.com/openshift/kubernetes/pkg/controller/volume/selinuxwarning/selinux_warning_controller.go
@@ -140,9 +140,9 @@ func NewController(
logger := klog.FromContext(ctx)
_, err = podInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
- AddFunc: func(obj interface{}) { c.addPod(logger, obj) },
- DeleteFunc: func(obj interface{}) { c.deletePod(logger, obj) },
- // Not watching updates: Pod volumes and SecurityContext are immutable after creation
+ AddFunc: func(obj interface{}) { c.enqueuePod(logger, obj) },
+ UpdateFunc: func(oldObj, newObj interface{}) { c.updatePod(logger, oldObj, newObj) },
+ DeleteFunc: func(obj interface{}) { c.enqueuePod(logger, obj) },
})
if err != nil {
return nil, err
@@ -178,7 +178,7 @@ func NewController(
return c, nil
}
-func (c *Controller) addPod(_ klog.Logger, obj interface{}) {
+func (c *Controller) enqueuePod(_ klog.Logger, obj interface{}) {
podRef, err := cache.DeletionHandlingObjectToName(obj)
if err != nil {
utilruntime.HandleError(fmt.Errorf("couldn't get key for pod %#v: %w", obj, err))
@@ -186,12 +186,29 @@ func (c *Controller) addPod(_ klog.Logger, obj interface{}) {
c.queue.Add(podRef)
}
-func (c *Controller) deletePod(_ klog.Logger, obj interface{}) {
- podRef, err := cache.DeletionHandlingObjectToName(obj)
- if err != nil {
- utilruntime.HandleError(fmt.Errorf("couldn't get key for pod %#v: %w", obj, err))
+func (c *Controller) updatePod(logger klog.Logger, oldObj, newObj interface{}) {
+ // Pod.Spec fields that are relevant to this controller are immutable after creation (i.e.
+ // pod volumes, SELinux labels, privileged flag). React to update only when the Pod
+ // reaches its final state - kubelet will unmount the Pod volumes and the controller should
+ // therefore remove them from the cache.
+ oldPod, ok := oldObj.(*v1.Pod)
+ if !ok {
+ return
}
- c.queue.Add(podRef)
+ newPod, ok := newObj.(*v1.Pod)
+ if !ok {
+ return
+ }
+
+ // This is an optimization. In theory, passing most pod updates to the controller queue should lead to noop.
+ // To save some CPU, pass only pod updates that can cause any action in the controller
+ if oldPod.Status.Phase == newPod.Status.Phase {
+ return
+ }
+ if newPod.Status.Phase != v1.PodFailed && newPod.Status.Phase != v1.PodSucceeded {
+ return
+ }
+ c.enqueuePod(logger, newObj)
}
func (c *Controller) addPVC(logger klog.Logger, obj interface{}) {
@@ -277,11 +294,7 @@ func (c *Controller) enqueueAllPodsForPVC(logger klog.Logger, namespace, name st
return
}
for _, obj := range objs {
- podRef, err := cache.DeletionHandlingObjectToName(obj)
- if err != nil {
- utilruntime.HandleError(fmt.Errorf("couldn't get key for pod %#v: %w", obj, err))
- }
- c.queue.Add(podRef)
+ c.enqueuePod(logger, obj)
}
}
@@ -401,6 +414,11 @@ func (c *Controller) sync(ctx context.Context, podRef cache.ObjectName) error {
logger.V(5).Info("Error getting pod from informer", "pod", klog.KObj(pod), "podUID", pod.UID, "err", err)
return err
}
+ if pod.Status.Phase == v1.PodFailed || pod.Status.Phase == v1.PodSucceeded {
+ // The pod has reached its final state and kubelet is unmounting is volumes.
+ // Remove them from the cache.
+ return c.syncPodDelete(ctx, podRef)
+ }
return c.syncPod(ctx, pod)
}
@@ -481,8 +499,15 @@ func (c *Controller) syncVolume(logger klog.Logger, pod *v1.Pod, spec *volume.Sp
changePolicy := v1.SELinuxChangePolicyMountOption
if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.SELinuxChangePolicy != nil {
changePolicy = *pod.Spec.SecurityContext.SELinuxChangePolicy
+ logger.V(5).Info("Using Pod SELinux change policy", "pod", klog.KObj(pod), "changePolicy", changePolicy)
}
- if !pluginSupportsSELinuxContextMount {
+ if !pluginSupportsSELinuxContextMount && changePolicy != v1.SELinuxChangePolicyRecursive {
+ logger.V(5).Info("Volume does not support SELinux context mount, setting changePolicy to Recursive", "pod", klog.KObj(pod), "volume", spec.Name())
+ changePolicy = v1.SELinuxChangePolicyRecursive
+ }
+
+ if seLinuxLabel == "" && changePolicy != v1.SELinuxChangePolicyRecursive {
+ logger.V(5).Info("Pod has empty SELinux label, setting changePolicy to Recursive", "pod", klog.KObj(pod))
changePolicy = v1.SELinuxChangePolicyRecursive
}
diff --git a/deps/github.com/openshift/kubernetes/pkg/controller/volume/selinuxwarning/selinux_warning_controller_test.go b/deps/github.com/openshift/kubernetes/pkg/controller/volume/selinuxwarning/selinux_warning_controller_test.go
index 3f863cac8a..8cc6c6d585 100644
--- a/deps/github.com/openshift/kubernetes/pkg/controller/volume/selinuxwarning/selinux_warning_controller_test.go
+++ b/deps/github.com/openshift/kubernetes/pkg/controller/volume/selinuxwarning/selinux_warning_controller_test.go
@@ -54,31 +54,34 @@ func TestSELinuxWarningController_Sync(t *testing.T) {
existingCSIDrivers []*storagev1.CSIDriver
existingPods []*v1.Pod
- pod cache.ObjectName
- conflicts []volumecache.Conflict
- expectError bool
- expectedAddedVolumes []addedVolume
- expectedEvents []string
- expectedDeletedPods []cache.ObjectName
+ pod cache.ObjectName
+ csiDriverSELinuxEnabled bool
+ conflicts []volumecache.Conflict
+ expectError bool
+ expectedAddedVolumes []addedVolume
+ expectedEvents []string
+ expectedDeletedPods []cache.ObjectName
}{
{
name: "existing pod with no volumes",
existingPods: []*v1.Pod{
- pod("pod1", "s0:c1,c2", nil),
+ pod("pod1", "s0:c1,c2", nil).build(),
},
- pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
- expectedEvents: nil,
- expectedAddedVolumes: nil,
+ pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
+ csiDriverSELinuxEnabled: true,
+ expectedEvents: nil,
+ expectedAddedVolumes: nil,
},
{
name: "existing pod with unbound PVC",
existingPods: []*v1.Pod{
- podWithPVC("pod1", "s0:c1,c2", nil, "non-existing-pvc", "vol1"),
+ pod("pod1", "s0:c1,c2", nil).withPVC("non-existing-pvc", "vol1").build(),
},
- pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
- expectError: true, // PVC is missing, add back to queue with exp. backoff
- expectedEvents: nil,
- expectedAddedVolumes: nil,
+ pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
+ csiDriverSELinuxEnabled: true,
+ expectError: true, // PVC is missing, add back to queue with exp. backoff
+ expectedEvents: nil,
+ expectedAddedVolumes: nil,
},
{
name: "existing pod with fully bound PVC",
@@ -89,10 +92,11 @@ func TestSELinuxWarningController_Sync(t *testing.T) {
pvBoundToPVC("pv1", "pvc1"),
},
existingPods: []*v1.Pod{
- podWithPVC("pod1", "s0:c1,c2", nil, "pvc1", "vol1"),
+ pod("pod1", "s0:c1,c2", nil).withPVC("pvc1", "vol1").build(),
},
- pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
- expectedEvents: nil,
+ pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
+ csiDriverSELinuxEnabled: true,
+ expectedEvents: nil,
expectedAddedVolumes: []addedVolume{
{
volumeName: "fake-plugin/pv1",
@@ -112,10 +116,11 @@ func TestSELinuxWarningController_Sync(t *testing.T) {
pvBoundToPVC("pv1", "pvc1"),
},
existingPods: []*v1.Pod{
- podWithPVC("pod1", "s0:c1,c2", ptr.To(v1.SELinuxChangePolicyRecursive), "pvc1", "vol1"),
+ pod("pod1", "s0:c1,c2", ptr.To(v1.SELinuxChangePolicyRecursive)).withPVC("pvc1", "vol1").build(),
},
- pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
- expectedEvents: nil,
+ pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
+ csiDriverSELinuxEnabled: true,
+ expectedEvents: nil,
expectedAddedVolumes: []addedVolume{
{
volumeName: "fake-plugin/pv1",
@@ -135,10 +140,11 @@ func TestSELinuxWarningController_Sync(t *testing.T) {
pvBoundToPVC("pv1", "pvc1"),
},
existingPods: []*v1.Pod{
- addInlineVolume(pod("pod1", "s0:c1,c2", nil)),
+ pod("pod1", "s0:c1,c2", nil).withInlineVolume().build(),
},
- pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
- expectedEvents: nil,
+ pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
+ csiDriverSELinuxEnabled: true,
+ expectedEvents: nil,
expectedAddedVolumes: []addedVolume{
{
volumeName: "fake-plugin/ebs.csi.aws.com-inlinevol1",
@@ -158,10 +164,11 @@ func TestSELinuxWarningController_Sync(t *testing.T) {
pvBoundToPVC("pv1", "pvc1"),
},
existingPods: []*v1.Pod{
- addInlineVolume(podWithPVC("pod1", "s0:c1,c2", nil, "pvc1", "vol1")),
+ pod("pod1", "s0:c1,c2", nil).withPVC("pvc1", "vol1").withInlineVolume().build(),
},
- pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
- expectedEvents: nil,
+ pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
+ csiDriverSELinuxEnabled: true,
+ expectedEvents: nil,
expectedAddedVolumes: []addedVolume{
{
volumeName: "fake-plugin/pv1",
@@ -188,10 +195,11 @@ func TestSELinuxWarningController_Sync(t *testing.T) {
pvBoundToPVC("pv1", "pvc1"),
},
existingPods: []*v1.Pod{
- podWithPVC("pod1", "s0:c1,c2", nil, "pvc1", "vol1"),
- pod("pod2", "s0:c98,c99", nil),
+ pod("pod1", "s0:c1,c2", nil).withPVC("pvc1", "vol1").build(),
+ pod("pod2", "s0:c98,c99", nil).build(),
},
- pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
+ pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
+ csiDriverSELinuxEnabled: true,
conflicts: []volumecache.Conflict{
{
PropertyName: "SELinuxLabel",
@@ -233,11 +241,12 @@ func TestSELinuxWarningController_Sync(t *testing.T) {
pvBoundToPVC("pv1", "pvc1"),
},
existingPods: []*v1.Pod{
- podWithPVC("pod1", "s0:c1,c2", ptr.To(v1.SELinuxChangePolicyRecursive), "pvc1", "vol1"),
- pod("pod2", "s0:c98,c99", ptr.To(v1.SELinuxChangePolicyRecursive)),
+ pod("pod1", "s0:c1,c2", ptr.To(v1.SELinuxChangePolicyRecursive)).withPVC("pvc1", "vol1").build(),
+ pod("pod2", "s0:c98,c99", ptr.To(v1.SELinuxChangePolicyRecursive)).build(),
},
- pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
- conflicts: []volumecache.Conflict{},
+ pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
+ csiDriverSELinuxEnabled: true,
+ conflicts: []volumecache.Conflict{},
expectedAddedVolumes: []addedVolume{
{
volumeName: "fake-plugin/pv1",
@@ -257,10 +266,11 @@ func TestSELinuxWarningController_Sync(t *testing.T) {
pvBoundToPVC("pv1", "pvc1"),
},
existingPods: []*v1.Pod{
- podWithPVC("pod1", "s0:c1,c2", ptr.To(v1.SELinuxChangePolicyRecursive), "pvc1", "vol1"),
- podWithPVC("pod2", "s0:c98,c99", ptr.To(v1.SELinuxChangePolicyMountOption), "pvc1", "vol1"),
+ pod("pod1", "s0:c1,c2", ptr.To(v1.SELinuxChangePolicyRecursive)).withPVC("pvc1", "vol1").build(),
+ pod("pod2", "s0:c98,c99", ptr.To(v1.SELinuxChangePolicyMountOption)).withPVC("pvc1", "vol1").build(),
},
- pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
+ pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
+ csiDriverSELinuxEnabled: true,
conflicts: []volumecache.Conflict{
{
PropertyName: "SELinuxChangePolicy",
@@ -302,10 +312,11 @@ func TestSELinuxWarningController_Sync(t *testing.T) {
pvBoundToPVC("pv1", "pvc1"),
},
existingPods: []*v1.Pod{
- podWithPVC("pod1", "s0:c1,c2", nil, "pvc1", "vol1"),
+ pod("pod1", "s0:c1,c2", nil).withPVC("pvc1", "vol1").build(),
// "pod2" does not exist
},
- pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
+ pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
+ csiDriverSELinuxEnabled: true,
conflicts: []volumecache.Conflict{
{
PropertyName: "SELinuxLabel",
@@ -338,16 +349,147 @@ func TestSELinuxWarningController_Sync(t *testing.T) {
`Normal SELinuxLabelConflict SELinuxLabel ":::s0:c1,c2" conflicts with pod pod2 that uses the same volume as this pod with SELinuxLabel ":::s0:c98,c99". If both pods land on the same node, only one of them may access the volume.`,
},
},
+ {
+ name: "empty label implies Recursive policy",
+ existingPVCs: []*v1.PersistentVolumeClaim{
+ pvcBoundToPV("pv1", "pvc1"),
+ },
+ existingPVs: []*v1.PersistentVolume{
+ pvBoundToPVC("pv1", "pvc1"),
+ },
+ existingPods: []*v1.Pod{
+ pod("pod1", "", ptr.To(v1.SELinuxChangePolicyMountOption)).withPVC("pvc1", "vol1").build(),
+ },
+ pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
+ csiDriverSELinuxEnabled: true,
+ conflicts: []volumecache.Conflict{},
+ expectedAddedVolumes: []addedVolume{
+ {
+ volumeName: "fake-plugin/pv1",
+ podKey: cache.ObjectName{Namespace: namespace, Name: "pod1"},
+ label: "",
+ changePolicy: v1.SELinuxChangePolicyRecursive, // Reset to Recursive when the label is empty
+ csiDriver: "ebs.csi.aws.com",
+ },
+ },
+ },
+ {
+ name: "pending pod is processed",
+ existingPVCs: []*v1.PersistentVolumeClaim{
+ pvcBoundToPV("pv1", "pvc1"),
+ },
+ existingPVs: []*v1.PersistentVolume{
+ pvBoundToPVC("pv1", "pvc1"),
+ },
+ existingPods: []*v1.Pod{
+ pod("pod1", "s0:c1,c2", nil).withPVC("pvc1", "vol1").withPhase(v1.PodPending).build(),
+ },
+ pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
+ csiDriverSELinuxEnabled: true,
+ expectedEvents: nil,
+ expectedAddedVolumes: []addedVolume{
+ {
+ volumeName: "fake-plugin/pv1",
+ podKey: cache.ObjectName{Namespace: namespace, Name: "pod1"},
+ label: ":::s0:c1,c2",
+ changePolicy: v1.SELinuxChangePolicyMountOption,
+ csiDriver: "ebs.csi.aws.com",
+ },
+ },
+ },
+ {
+ name: "unknown pod is processed",
+ existingPVCs: []*v1.PersistentVolumeClaim{
+ pvcBoundToPV("pv1", "pvc1"),
+ },
+ existingPVs: []*v1.PersistentVolume{
+ pvBoundToPVC("pv1", "pvc1"),
+ },
+ existingPods: []*v1.Pod{
+ pod("pod1", "s0:c1,c2", nil).withPVC("pvc1", "vol1").withPhase(v1.PodUnknown).build(),
+ },
+ pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
+ csiDriverSELinuxEnabled: true,
+ expectedEvents: nil,
+ expectedAddedVolumes: []addedVolume{
+ {
+ volumeName: "fake-plugin/pv1",
+ podKey: cache.ObjectName{Namespace: namespace, Name: "pod1"},
+ label: ":::s0:c1,c2",
+ changePolicy: v1.SELinuxChangePolicyMountOption,
+ csiDriver: "ebs.csi.aws.com",
+ },
+ },
+ },
+ {
+ name: "succeeded pod is removed from the cache",
+ existingPVCs: []*v1.PersistentVolumeClaim{
+ pvcBoundToPV("pv1", "pvc1"),
+ },
+ existingPVs: []*v1.PersistentVolume{
+ pvBoundToPVC("pv1", "pvc1"),
+ },
+ existingPods: []*v1.Pod{
+ pod("pod1", "s0:c1,c2", nil).withPVC("pvc1", "vol1").withPhase(v1.PodSucceeded).build(),
+ },
+ pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
+ csiDriverSELinuxEnabled: true,
+ expectedEvents: nil,
+ expectedAddedVolumes: nil,
+ expectedDeletedPods: []cache.ObjectName{{Namespace: namespace, Name: "pod1"}},
+ },
+ {
+ name: "failed pod is removed from the cache",
+ existingPVCs: []*v1.PersistentVolumeClaim{
+ pvcBoundToPV("pv1", "pvc1"),
+ },
+ existingPVs: []*v1.PersistentVolume{
+ pvBoundToPVC("pv1", "pvc1"),
+ },
+ existingPods: []*v1.Pod{
+ pod("pod1", "s0:c1,c2", nil).withPVC("pvc1", "vol1").withPhase(v1.PodFailed).build(),
+ },
+ pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
+ csiDriverSELinuxEnabled: true,
+ expectedEvents: nil,
+ expectedAddedVolumes: nil,
+ expectedDeletedPods: []cache.ObjectName{{Namespace: namespace, Name: "pod1"}},
+ },
{
name: "deleted pod",
existingPods: []*v1.Pod{
// "pod1" does not exist in the informer
},
- pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
- expectError: false,
- expectedEvents: nil,
- expectedAddedVolumes: nil,
- expectedDeletedPods: []cache.ObjectName{{Namespace: namespace, Name: "pod1"}},
+ pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
+ csiDriverSELinuxEnabled: true,
+ expectError: false,
+ expectedEvents: nil,
+ expectedAddedVolumes: nil,
+ expectedDeletedPods: []cache.ObjectName{{Namespace: namespace, Name: "pod1"}},
+ },
+ {
+ name: "existing pod with fully bound PVC and CSIDriver.SELinuxMount disabled",
+ existingPVCs: []*v1.PersistentVolumeClaim{
+ pvcBoundToPV("pv1", "pvc1"),
+ },
+ existingPVs: []*v1.PersistentVolume{
+ pvBoundToPVC("pv1", "pvc1"),
+ },
+ existingPods: []*v1.Pod{
+ pod("pod1", "s0:c1,c2", nil).withPVC("pvc1", "vol1").build(),
+ },
+ pod: cache.ObjectName{Namespace: namespace, Name: "pod1"},
+ csiDriverSELinuxEnabled: false,
+ expectedEvents: nil,
+ expectedAddedVolumes: []addedVolume{
+ {
+ volumeName: "fake-plugin/pv1",
+ podKey: cache.ObjectName{Namespace: namespace, Name: "pod1"},
+ label: "", // Label is cleared when the CSI driver does not support SELinuxMount
+ changePolicy: v1.SELinuxChangePolicyRecursive, // Reset to Recursive when the CSI driver does not support SELinuxMount
+ csiDriver: "ebs.csi.aws.com", // The PV is a fake EBS volume
+ },
+ },
},
}
@@ -357,7 +499,7 @@ func TestSELinuxWarningController_Sync(t *testing.T) {
_, ctx := ktesting.NewTestContext(t)
_, plugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
- plugin.SupportsSELinux = true
+ plugin.SupportsSELinux = tt.csiDriverSELinuxEnabled
fakeClient := fake.NewClientset()
fakeInformerFactory := informers.NewSharedInformerFactory(fakeClient, controller.NoResyncPeriodFunc())
@@ -490,49 +632,63 @@ func pvcBoundToPV(pvName, pvcName string) *v1.PersistentVolumeClaim {
return pvc
}
-func pod(podName, level string, changePolicy *v1.PodSELinuxChangePolicy) *v1.Pod {
+type podBuilder struct {
+ pod *v1.Pod
+}
+
+func pod(podName, level string, changePolicy *v1.PodSELinuxChangePolicy) *podBuilder {
var opts *v1.SELinuxOptions
if level != "" {
opts = &v1.SELinuxOptions{
Level: level,
}
}
- return &v1.Pod{
- ObjectMeta: metav1.ObjectMeta{
- Namespace: "ns1",
- Name: podName,
- },
- Spec: v1.PodSpec{
- Containers: []v1.Container{
- {
- Name: "container1",
- Image: "image1",
- VolumeMounts: []v1.VolumeMount{
- {
- Name: "vol1",
- MountPath: "/mnt",
+ return &podBuilder{
+ pod: &v1.Pod{
+ ObjectMeta: metav1.ObjectMeta{
+ Namespace: "ns1",
+ Name: podName,
+ },
+ Spec: v1.PodSpec{
+ Containers: []v1.Container{
+ {
+ Name: "container1",
+ Image: "image1",
+ VolumeMounts: []v1.VolumeMount{
+ {
+ Name: "vol1",
+ MountPath: "/mnt",
+ },
},
},
},
- },
- SecurityContext: &v1.PodSecurityContext{
- SELinuxChangePolicy: changePolicy,
- SELinuxOptions: opts,
- },
- Volumes: []v1.Volume{
- {
- Name: "emptyDir1",
- VolumeSource: v1.VolumeSource{
- EmptyDir: &v1.EmptyDirVolumeSource{},
+ SecurityContext: &v1.PodSecurityContext{
+ SELinuxChangePolicy: changePolicy,
+ SELinuxOptions: opts,
+ },
+ Volumes: []v1.Volume{
+ {
+ Name: "emptyDir1",
+ VolumeSource: v1.VolumeSource{
+ EmptyDir: &v1.EmptyDirVolumeSource{},
+ },
},
},
},
+ Status: v1.PodStatus{
+ Phase: v1.PodRunning,
+ },
},
}
}
-func addInlineVolume(pod *v1.Pod) *v1.Pod {
- pod.Spec.Volumes = append(pod.Spec.Volumes, v1.Volume{
+func (b *podBuilder) withPhase(phase v1.PodPhase) *podBuilder {
+ b.pod.Status.Phase = phase
+ return b
+}
+
+func (b *podBuilder) withInlineVolume() *podBuilder {
+ b.pod.Spec.Volumes = append(b.pod.Spec.Volumes, v1.Volume{
Name: "inlineVolume",
VolumeSource: v1.VolumeSource{
AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{
@@ -540,17 +696,15 @@ func addInlineVolume(pod *v1.Pod) *v1.Pod {
},
},
})
- pod.Spec.Containers[0].VolumeMounts = append(pod.Spec.Containers[0].VolumeMounts, v1.VolumeMount{
+ b.pod.Spec.Containers[0].VolumeMounts = append(b.pod.Spec.Containers[0].VolumeMounts, v1.VolumeMount{
Name: "inlineVolume",
MountPath: "/mnt",
})
-
- return pod
+ return b
}
-func podWithPVC(podName, label string, changePolicy *v1.PodSELinuxChangePolicy, pvcName, volumeName string) *v1.Pod {
- pod := pod(podName, label, changePolicy)
- pod.Spec.Volumes = append(pod.Spec.Volumes, v1.Volume{
+func (b *podBuilder) withPVC(pvcName, volumeName string) *podBuilder {
+ b.pod.Spec.Volumes = append(b.pod.Spec.Volumes, v1.Volume{
Name: volumeName,
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
@@ -558,11 +712,15 @@ func podWithPVC(podName, label string, changePolicy *v1.PodSELinuxChangePolicy,
},
},
})
- pod.Spec.Containers[0].VolumeMounts = append(pod.Spec.Containers[0].VolumeMounts, v1.VolumeMount{
+ b.pod.Spec.Containers[0].VolumeMounts = append(b.pod.Spec.Containers[0].VolumeMounts, v1.VolumeMount{
Name: volumeName,
MountPath: "/mnt",
})
- return pod
+ return b
+}
+
+func (b *podBuilder) build() *v1.Pod {
+ return b.pod
}
type addedVolume struct {
diff --git a/deps/github.com/openshift/kubernetes/test/e2e/storage/csimock/base.go b/deps/github.com/openshift/kubernetes/test/e2e/storage/csimock/base.go
index 4c51a11a31..86c75e4850 100644
--- a/deps/github.com/openshift/kubernetes/test/e2e/storage/csimock/base.go
+++ b/deps/github.com/openshift/kubernetes/test/e2e/storage/csimock/base.go
@@ -149,6 +149,7 @@ const (
var (
errPodCompleted = fmt.Errorf("pod ran to completion")
errNotEnoughSpace = errors.New(errReasonNotEnoughSpace)
+ sleepCommand = []string{"sleep", "infinity"}
)
func newMockDriverSetup(f *framework.Framework) *mockDriverSetup {
@@ -474,7 +475,15 @@ func (m *mockDriverSetup) createPodWithFSGroup(ctx context.Context, fsGroup *int
return class, claim, pod
}
-func (m *mockDriverSetup) createPodWithSELinux(ctx context.Context, accessModes []v1.PersistentVolumeAccessMode, mountOptions []string, seLinuxOpts *v1.SELinuxOptions, policy *v1.PodSELinuxChangePolicy, privileged bool) (*storagev1.StorageClass, *v1.PersistentVolumeClaim, *v1.Pod) {
+func (m *mockDriverSetup) createPodWithSELinux(
+ ctx context.Context,
+ accessModes []v1.PersistentVolumeAccessMode,
+ mountOptions []string,
+ seLinuxOpts *v1.SELinuxOptions,
+ policy *v1.PodSELinuxChangePolicy,
+ privileged bool,
+ command []string) (*storagev1.StorageClass, *v1.PersistentVolumeClaim, *v1.Pod) {
+
ginkgo.By("Creating pod with SELinux context")
f := m.f
nodeSelection := m.config.ClientNodeSelection
@@ -491,7 +500,7 @@ func (m *mockDriverSetup) createPodWithSELinux(ctx context.Context, accessModes
ReclaimPolicy: m.tp.reclaimPolicy,
}
class, claim := createClaim(ctx, f.ClientSet, scTest, nodeSelection, m.tp.scName, f.Namespace.Name, accessModes)
- pod, err := startPausePodWithSELinuxOptions(f.ClientSet, claim, nodeSelection, f.Namespace.Name, seLinuxOpts, policy, privileged)
+ pod, err := startPausePodWithSELinuxOptions(f.ClientSet, claim, nodeSelection, f.Namespace.Name, seLinuxOpts, policy, privileged, command)
framework.ExpectNoError(err, "Failed to create pause pod with SELinux context %s: %v", seLinuxOpts, err)
if class != nil {
@@ -866,7 +875,19 @@ func startBusyBoxPodWithVolumeSource(cs clientset.Interface, volumeSource v1.Vol
return cs.CoreV1().Pods(ns).Create(context.TODO(), pod, metav1.CreateOptions{})
}
-func startPausePodWithSELinuxOptions(cs clientset.Interface, pvc *v1.PersistentVolumeClaim, node e2epod.NodeSelection, ns string, seLinuxOpts *v1.SELinuxOptions, policy *v1.PodSELinuxChangePolicy, privileged bool) (*v1.Pod, error) {
+func startPausePodWithSELinuxOptions(
+ cs clientset.Interface,
+ pvc *v1.PersistentVolumeClaim,
+ node e2epod.NodeSelection,
+ ns string,
+ seLinuxOpts *v1.SELinuxOptions,
+ policy *v1.PodSELinuxChangePolicy,
+ privileged bool,
+ command []string) (*v1.Pod, error) {
+
+ if len(command) == 0 {
+ command = sleepCommand
+ }
pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "pvc-volume-tester-",
@@ -878,8 +899,9 @@ func startPausePodWithSELinuxOptions(cs clientset.Interface, pvc *v1.PersistentV
},
Containers: []v1.Container{
{
- Name: "volume-tester",
- Image: imageutils.GetE2EImage(imageutils.Pause),
+ Name: "volume-tester",
+ Image: e2epod.GetDefaultTestImage(),
+ Command: command,
SecurityContext: &v1.SecurityContext{
Privileged: &privileged,
},
diff --git a/deps/github.com/openshift/kubernetes/test/e2e/storage/csimock/csi_selinux_mount.go b/deps/github.com/openshift/kubernetes/test/e2e/storage/csimock/csi_selinux_mount.go
index 3a7045cbaf..08c0e54857 100644
--- a/deps/github.com/openshift/kubernetes/test/e2e/storage/csimock/csi_selinux_mount.go
+++ b/deps/github.com/openshift/kubernetes/test/e2e/storage/csimock/csi_selinux_mount.go
@@ -298,7 +298,7 @@ var _ = utils.SIGDescribe("CSI Mock selinux on mount", func() {
// Act
ginkgo.By("Starting the initial pod")
accessModes := []v1.PersistentVolumeAccessMode{t.volumeMode}
- _, claim, pod := m.createPodWithSELinux(ctx, accessModes, t.mountOptions, t.firstPodSELinuxOpts, t.firstPodChangePolicy, false /* privileged */)
+ _, claim, pod := m.createPodWithSELinux(ctx, accessModes, t.mountOptions, t.firstPodSELinuxOpts, t.firstPodChangePolicy, false /* privileged */, sleepCommand)
err := e2epod.WaitForPodNameRunningInNamespace(ctx, m.cs, pod.Name, pod.Namespace)
framework.ExpectNoError(err, "starting the initial pod")
@@ -331,7 +331,15 @@ var _ = utils.SIGDescribe("CSI Mock selinux on mount", func() {
pod, err = m.cs.CoreV1().Pods(pod.Namespace).Get(ctx, pod.Name, metav1.GetOptions{})
framework.ExpectNoError(err, "getting the initial pod")
nodeSelection := e2epod.NodeSelection{Name: pod.Spec.NodeName}
- pod2, err := startPausePodWithSELinuxOptions(f.ClientSet, claim, nodeSelection, f.Namespace.Name, t.secondPodSELinuxOpts, t.secondPodChangePolicy, false /* privileged */)
+ pod2, err := startPausePodWithSELinuxOptions(
+ f.ClientSet,
+ claim,
+ nodeSelection,
+ f.Namespace.Name,
+ t.secondPodSELinuxOpts,
+ t.secondPodChangePolicy,
+ false, /* privileged */
+ sleepCommand)
framework.ExpectNoError(err, "creating second pod with SELinux context %s", t.secondPodSELinuxOpts)
m.pods = append(m.pods, pod2)
@@ -454,6 +462,7 @@ var _ = utils.SIGDescribe("CSI Mock selinux on mount metrics and SELinuxWarningC
firstPodSELinuxOpts *v1.SELinuxOptions
firstPodChangePolicy *v1.PodSELinuxChangePolicy
firstPodPrivileged bool
+ firstPodTargetPhase v1.PodPhase // Phase the first pod should reach before the second pod is created. Empty value means Running
secondPodSELinuxOpts *v1.SELinuxOptions
secondPodChangePolicy *v1.PodSELinuxChangePolicy
secondPodPrivileged bool
@@ -719,6 +728,74 @@ var _ = utils.SIGDescribe("CSI Mock selinux on mount metrics and SELinuxWarningC
expectControllerConflictProperty: "SELinuxLabel",
testTags: []interface{}{framework.WithFeatureGate(features.SELinuxMount)},
},
+ {
+ name: "error is not bumped on a finished Pod with a different context on RWO volume and SELinuxMount enabled",
+ csiDriverSELinuxEnabled: true,
+ firstPodSELinuxOpts: &seLinuxOpts1,
+ firstPodTargetPhase: v1.PodSucceeded,
+ secondPodSELinuxOpts: &seLinuxOpts2,
+ volumeMode: v1.ReadWriteOnce,
+ waitForSecondPodStart: true,
+ // The volume is unmounted between the first and the second Pod, so admitted_total increases,
+ expectNodeIncreases: sets.New[string]("volume_manager_selinux_volumes_admitted_total"),
+ testTags: []interface{}{framework.WithFeatureGate(features.SELinuxMount)},
+ },
+ {
+ name: "error is not bumped on a failed Pod with a different context on RWO volume and SELinuxMount enabled",
+ csiDriverSELinuxEnabled: true,
+ firstPodSELinuxOpts: &seLinuxOpts1,
+ firstPodTargetPhase: v1.PodFailed,
+ secondPodSELinuxOpts: &seLinuxOpts2,
+ volumeMode: v1.ReadWriteOnce,
+ waitForSecondPodStart: true,
+ // The volume is unmounted between the first and the second Pod, so admitted_total increases,
+ expectNodeIncreases: sets.New[string]("volume_manager_selinux_volumes_admitted_total"),
+ testTags: []interface{}{framework.WithFeatureGate(features.SELinuxMount)},
+ },
+ {
+ name: "warning is not bumped on RWO volume with CSIDriver.SELinuxMount disabled and mismatched labels",
+ csiDriverSELinuxEnabled: false,
+ firstPodSELinuxOpts: &seLinuxOpts1,
+ secondPodSELinuxOpts: &seLinuxOpts2,
+ volumeMode: v1.ReadWriteOnce,
+ waitForSecondPodStart: true,
+ expectNodeIncreases: sets.New[string]( /* no metric is increased, admitted_total was already increased when the first pod started */ ),
+ testTags: []interface{}{framework.WithFeatureGate(features.SELinuxMount)},
+ },
+ {
+ name: "warning is not bumped on RWX volume with CSIDriver.SELinuxMount disabled and mismatched labels",
+ csiDriverSELinuxEnabled: false,
+ firstPodSELinuxOpts: &seLinuxOpts1,
+ secondPodSELinuxOpts: &seLinuxOpts2,
+ volumeMode: v1.ReadWriteMany,
+ waitForSecondPodStart: true,
+ expectNodeIncreases: sets.New[string]( /* no metric is increased, admitted_total was already increased when the first pod started */ ),
+ testTags: []interface{}{framework.WithFeatureGate(features.SELinuxMount)},
+ },
+ {
+ name: "warning is not bumped on RWO volume with CSIDriver.SELinuxMount disabled and mismatched policies",
+ csiDriverSELinuxEnabled: false,
+ firstPodSELinuxOpts: &seLinuxOpts1,
+ firstPodChangePolicy: &recursive,
+ secondPodSELinuxOpts: &seLinuxOpts1,
+ secondPodChangePolicy: &mount,
+ volumeMode: v1.ReadWriteOnce,
+ waitForSecondPodStart: true,
+ expectNodeIncreases: sets.New[string]( /* no metric is increased, admitted_total was already increased when the first pod started */ ),
+ testTags: []interface{}{framework.WithFeatureGate(features.SELinuxMount)},
+ },
+ {
+ name: "warning is not bumped on RWX volume with CSIDriver.SELinuxMount disabled and mismatched policies",
+ csiDriverSELinuxEnabled: false,
+ firstPodSELinuxOpts: &seLinuxOpts1,
+ firstPodChangePolicy: &recursive,
+ secondPodSELinuxOpts: &seLinuxOpts1,
+ secondPodChangePolicy: &mount,
+ volumeMode: v1.ReadWriteMany,
+ waitForSecondPodStart: true,
+ expectNodeIncreases: sets.New[string]( /* no metric is increased, admitted_total was already increased when the first pod started */ ),
+ testTags: []interface{}{framework.WithFeatureGate(features.SELinuxMount)},
+ },
}
for _, t := range tests {
t := t
@@ -726,6 +803,9 @@ var _ = utils.SIGDescribe("CSI Mock selinux on mount metrics and SELinuxWarningC
if processLabel == "" {
e2eskipper.Skipf("SELinux tests are supported only on %+v", getSupportedSELinuxDistros())
}
+ if t.firstPodTargetPhase == "" {
+ t.firstPodTargetPhase = v1.PodRunning
+ }
// Some metrics use CSI driver name as a label, which is "csi-mock-" + the namespace name.
volumePluginLabel := "volume_plugin=\"kubernetes.io/csi/csi-mock-" + f.Namespace.Name + "\""
@@ -744,9 +824,24 @@ var _ = utils.SIGDescribe("CSI Mock selinux on mount metrics and SELinuxWarningC
ginkgo.By("Starting the first pod")
accessModes := []v1.PersistentVolumeAccessMode{t.volumeMode}
- _, claim, pod := m.createPodWithSELinux(ctx, accessModes, []string{}, t.firstPodSELinuxOpts, t.firstPodChangePolicy, t.firstPodPrivileged)
- err = e2epod.WaitForPodNameRunningInNamespace(ctx, m.cs, pod.Name, pod.Namespace)
- framework.ExpectNoError(err, "starting the initial pod")
+ command := sleepCommand
+ switch t.firstPodTargetPhase {
+ case v1.PodSucceeded:
+ command = []string{"/bin/true"}
+ case v1.PodFailed:
+ command = []string{"/bin/false"}
+ }
+ _, claim, pod := m.createPodWithSELinux(ctx, accessModes, []string{}, t.firstPodSELinuxOpts, t.firstPodChangePolicy, t.firstPodPrivileged, command)
+
+ switch t.firstPodTargetPhase {
+ case v1.PodRunning:
+ err = e2epod.WaitForPodNameRunningInNamespace(ctx, m.cs, pod.Name, pod.Namespace)
+ framework.ExpectNoError(err, "starting the initial pod")
+ case v1.PodSucceeded, v1.PodFailed:
+ ginkgo.By("Waiting for the first pod to complete")
+ err = e2epod.WaitForPodNoLongerRunningInNamespace(ctx, m.cs, pod.Name, pod.Namespace)
+ framework.ExpectNoError(err, "starting and completing the initial pod")
+ }
ginkgo.By("Grabbing initial metrics")
pod, err = m.cs.CoreV1().Pods(pod.Namespace).Get(ctx, pod.Name, metav1.GetOptions{})
@@ -759,7 +854,15 @@ var _ = utils.SIGDescribe("CSI Mock selinux on mount metrics and SELinuxWarningC
ginkgo.By("Starting the second pod")
// Skip scheduler, it would block scheduling the second pod with ReadWriteOncePod PV.
nodeSelection := e2epod.NodeSelection{Name: pod.Spec.NodeName}
- pod2, err := startPausePodWithSELinuxOptions(f.ClientSet, claim, nodeSelection, f.Namespace.Name, t.secondPodSELinuxOpts, t.secondPodChangePolicy, t.secondPodPrivileged)
+ pod2, err := startPausePodWithSELinuxOptions(
+ f.ClientSet,
+ claim,
+ nodeSelection,
+ f.Namespace.Name,
+ t.secondPodSELinuxOpts,
+ t.secondPodChangePolicy,
+ t.secondPodPrivileged,
+ sleepCommand)
framework.ExpectNoError(err, "creating second pod with SELinux context %s", t.secondPodSELinuxOpts)
m.pods = append(m.pods, pod2)
@@ -795,6 +898,9 @@ var _ = utils.SIGDescribe("CSI Mock selinux on mount metrics and SELinuxWarningC
// Check the controler generated event on the second pod
err = waitForConflictEvent(ctx, m.cs, pod2, pod, t.expectControllerConflictProperty, f.Timeouts.PodStart)
framework.ExpectNoError(err, "while waiting for an event on the second pod")
+ } else {
+ err := checkForNoConflictEvents(ctx, m.cs, pod, pod2)
+ framework.ExpectNoError(err, "ensuring there are no SELinux conflict events")
}
}
// t.testTags is array and it's not possible to use It("name", func(){xxx}, t.testTags...)
@@ -974,6 +1080,29 @@ func waitForConflictEvent(ctx context.Context, cs clientset.Interface, pod, othe
return e2eevents.WaitTimeoutForEvent(ctx, cs, pod.Namespace, eventSelector, msg, timeout)
}
+func checkForNoConflictEvents(ctx context.Context, cs clientset.Interface, pod, otherPod *v1.Pod) error {
+ eventSelector := fields.Set{
+ "involvedObject.kind": "Pod",
+ "involvedObject.name": pod.Name,
+ "involvedObject.namespace": pod.Namespace,
+ }.AsSelector().String()
+ options := metav1.ListOptions{FieldSelector: eventSelector}
+
+ events, err := cs.CoreV1().Events(pod.Namespace).List(ctx, options)
+ if err != nil {
+ return fmt.Errorf("error getting events: %w", err)
+ }
+
+ msg := fmt.Sprintf("conflicts with pod %s that uses the same volume as this pod", otherPod.Name)
+ ginkgo.By(fmt.Sprintf("Checking for the SELinux controller events on pod %q: %q", pod.Name, msg))
+ for _, event := range events.Items {
+ if strings.Contains(event.Message, msg) {
+ return fmt.Errorf("conflict event found: %s", event.Message)
+ }
+ }
+ return nil
+}
+
func dumpMetrics(metrics map[string]float64) {
// Print the metrics sorted by metric name for better readability
keys := make([]string, 0, len(metrics))
diff --git a/etcd/go.mod b/etcd/go.mod
index 308f95e434..5397d665c3 100644
--- a/etcd/go.mod
+++ b/etcd/go.mod
@@ -1,17 +1,14 @@
module github.com/openshift/microshift/etcd
-go 1.24.0
+go 1.25.0
-require github.com/openshift/microshift v0.0.0
-
-replace (
- github.com/openshift/microshift => ../
-)
+replace github.com/openshift/microshift => ../
require (
github.com/openshift/api v0.0.0-20251214014457-bfa868a22401
github.com/openshift/build-machinery-go v0.0.0-20251023084048-5d77c1a5e5af
- github.com/spf13/cobra v1.9.1
+ github.com/openshift/microshift v0.0.0-00010101000000-000000000000
+ github.com/spf13/cobra v1.10.0
go.etcd.io/etcd/server/v3 v3.6.4
k8s.io/apimachinery v1.34.2
k8s.io/cli-runtime v1.34.2
@@ -22,7 +19,9 @@ require (
)
require (
+ github.com/apparentlymart/go-cidr v1.1.0 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
+ github.com/evanphx/json-patch v4.12.0+incompatible // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
@@ -35,7 +34,8 @@ require (
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/oklog/run v1.2.0 // indirect
- github.com/openshift/library-go v0.0.0-20251112091634-ab97ebb73f0f // indirect
+ github.com/openshift/library-go v0.0.0-20260121132910-dc3a1c884c04 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/squat/generic-device-plugin v0.0.0-20251019101956-043a51e18f31 // indirect
@@ -45,12 +45,12 @@ require (
go.etcd.io/raft/v3 v3.6.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel/metric v1.37.0 // indirect
- go.yaml.in/yaml/v2 v2.4.2 // indirect
+ go.yaml.in/yaml/v2 v2.4.3 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
- golang.org/x/sync v0.17.0 // indirect
+ golang.org/x/sync v0.18.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250804133106-a7a43d27e69b // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1 // indirect
- gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
+ gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
k8s.io/apiserver v1.34.2 // indirect
k8s.io/kubelet v1.34.2 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
@@ -60,7 +60,6 @@ require (
require (
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/MakeNowJust/heredoc v1.0.0 // indirect
- github.com/apparentlymart/go-cidr v1.1.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
@@ -70,7 +69,6 @@ require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
- github.com/evanphx/json-patch v4.12.0+incompatible // indirect
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
github.com/go-errors/errors v1.4.2 // indirect
github.com/go-logr/logr v1.4.3 // indirect
@@ -97,7 +95,6 @@ require (
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
- github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.23.2 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.66.1 // indirect
@@ -122,12 +119,12 @@ require (
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
- golang.org/x/crypto v0.42.0 // indirect
- golang.org/x/net v0.43.0 // indirect
+ golang.org/x/crypto v0.45.0 // indirect
+ golang.org/x/net v0.47.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
- golang.org/x/sys v0.36.0 // indirect
- golang.org/x/term v0.35.0 // indirect
- golang.org/x/text v0.29.0 // indirect
+ golang.org/x/sys v0.38.0 // indirect
+ golang.org/x/term v0.37.0 // indirect
+ golang.org/x/text v0.31.0 // indirect
golang.org/x/time v0.9.0 // indirect
google.golang.org/grpc v1.76.0 // indirect
google.golang.org/protobuf v1.36.8 // indirect
@@ -136,9 +133,9 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v1.34.2 // indirect
k8s.io/client-go v1.34.2 // indirect
- k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect
+ k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect
- sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
+ sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
sigs.k8s.io/kustomize/api v0.20.1 // indirect
sigs.k8s.io/kustomize/kyaml v0.20.1 // indirect
)
diff --git a/etcd/go.sum b/etcd/go.sum
index d8723d369f..9e4f0844e6 100644
--- a/etcd/go.sum
+++ b/etcd/go.sum
@@ -74,8 +74,8 @@ github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7O
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
-github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
+github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
+github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
@@ -147,8 +147,8 @@ github.com/openshift/etcd/pkg/v3 v3.5.0-alpha.0.0.20260202131331-6a0992267004 h1
github.com/openshift/etcd/pkg/v3 v3.5.0-alpha.0.0.20260202131331-6a0992267004/go.mod h1:uqrXrzmMIJDEy5j00bCqhVLzR5jEJIwDp5wTlLwPGOU=
github.com/openshift/etcd/server/v3 v3.5.0-alpha.0.0.20260202131331-6a0992267004 h1:cyY8/K2U6XIxYUUxQypattfKCUi/0x59N5Lr2seP/mQ=
github.com/openshift/etcd/server/v3 v3.5.0-alpha.0.0.20260202131331-6a0992267004/go.mod h1:PLuhyVXz8WWRhzXDsl3A3zv/+aK9e4A9lpQkqawIaH0=
-github.com/openshift/library-go v0.0.0-20251112091634-ab97ebb73f0f h1:r1pLosA7z3+t+lzW29FU54sg4/pAWu+lsKD0L5Gx3wg=
-github.com/openshift/library-go v0.0.0-20251112091634-ab97ebb73f0f/go.mod h1:ErDfiIrPHH+menTP/B4LKd0nxFDdvCbTamAc6SWMIh8=
+github.com/openshift/library-go v0.0.0-20260121132910-dc3a1c884c04 h1:Fm9C8pT4l6VjpdqdhI1cBX9Y3D3S+rFxptVhCPBbMAI=
+github.com/openshift/library-go v0.0.0-20260121132910-dc3a1c884c04/go.mod h1:nIzWQQE49XbiKizVnVOip9CEB7HJ0hoJwNi3g3YKnKc=
github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20251001123353-fd5b1fb35db1 h1:PMTgifBcBRLJJiM+LgSzPDTk9/Rx4qS09OUrfpY6GBQ=
github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20251001123353-fd5b1fb35db1/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
@@ -177,9 +177,9 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
-github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
-github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
-github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/cobra v1.10.0 h1:a5/WeUlSDCvV5a45ljW2ZFtV0bTDpkfSAj3uqB6Sc+0=
+github.com/spf13/cobra v1.10.0/go.mod h1:9dhySC7dnTtEiqzmqfkLj47BslqLCUPMXjG2lj/NgoE=
+github.com/spf13/pflag v1.0.8/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/squat/generic-device-plugin v0.0.0-20251019101956-043a51e18f31 h1:wPJNupO/W9VJkwf/5vVnEReuS3pf5u+V+RGv6TOPrLM=
@@ -237,15 +237,15 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
-go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
-go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
+go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
+go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
-golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
+golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
+golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -254,15 +254,15 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
-golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
+golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
+golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
-golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
+golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
+golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -274,24 +274,24 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
-golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
+golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
+golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
-golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
+golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
+golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
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.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
-golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
+golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
+golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-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 v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
+golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -309,8 +309,8 @@ google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXn
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
-gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
-gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
+gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo=
+gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
@@ -320,12 +320,12 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
-k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA=
-k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts=
+k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE=
+k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ=
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck=
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
-sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
-sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
+sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
+sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/kustomize/api v0.20.1 h1:iWP1Ydh3/lmldBnH/S5RXgT98vWYMaTUL1ADcr+Sv7I=
sigs.k8s.io/kustomize/api v0.20.1/go.mod h1:t6hUFxO+Ph0VxIk1sKp1WS0dOjbPCtLJ4p8aADLwqjM=
sigs.k8s.io/kustomize/kyaml v0.20.1 h1:PCMnA2mrVbRP3NIB6v9kYCAc38uvFLVs8j/CD567A78=
diff --git a/etcd/vendor/github.com/openshift/library-go/pkg/crypto/crypto.go b/etcd/vendor/github.com/openshift/library-go/pkg/crypto/crypto.go
index 33a09ae16e..bff6155c2f 100644
--- a/etcd/vendor/github.com/openshift/library-go/pkg/crypto/crypto.go
+++ b/etcd/vendor/github.com/openshift/library-go/pkg/crypto/crypto.go
@@ -242,35 +242,41 @@ func ValidCipherSuites() []string {
sort.Strings(validCipherSuites)
return validCipherSuites
}
+
+// DefaultCiphers returns the default cipher suites for TLS connections.
+//
+// RECOMMENDATION: Instead of relying on this function directly, consumers should respect
+// TLSSecurityProfile settings from one of the OpenShift API configuration resources:
+// - For API servers: Use apiserver.config.openshift.io/cluster Spec.TLSSecurityProfile
+// - For ingress controllers: Use operator.openshift.io/v1 IngressController Spec.TLSSecurityProfile
+// - For kubelet: Use machineconfiguration.openshift.io/v1 KubeletConfig Spec.TLSSecurityProfile
+//
+// These API resources allow cluster administrators to choose between Old, Intermediate,
+// Modern, or Custom TLS profiles. Components should observe these settings.
func DefaultCiphers() []uint16 {
- // HTTP/2 mandates TLS 1.2 or higher with an AEAD cipher
- // suite (GCM, Poly1305) and ephemeral key exchange (ECDHE, DHE) for
- // perfect forward secrecy. Servers may provide additional cipher
- // suites for backwards compatibility with HTTP/1.1 clients.
- // See RFC7540, section 9.2 (Use of TLS Features) and Appendix A
- // (TLS 1.2 Cipher Suite Black List).
+ // Aligned with intermediate profile of the 5.7 version of the Mozilla Server
+ // Side TLS guidelines found at: https://ssl-config.mozilla.org/guidelines/5.7.json
+ //
+ // Latest guidelines: https://ssl-config.mozilla.org/guidelines/latest.json
+ //
+ // This profile provides strong security with wide compatibility.
+ // It requires TLS 1.2+ and uses only AEAD cipher suites (GCM, ChaCha20-Poly1305)
+ // with ECDHE key exchange for perfect forward secrecy.
+ //
+ // All CBC-mode ciphers have been removed due to padding oracle vulnerabilities.
+ // All RSA key exchange ciphers have been removed due to lack of perfect forward secrecy.
+ //
+ // HTTP/2 compliance: All ciphers are compliant with RFC7540, section 9.2.
return []uint16{
+ // TLS 1.2 cipher suites with ECDHE + AEAD
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
- tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, // required by http/2
+ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, // required by HTTP/2
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
- tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, // forbidden by http/2, not flagged by http2isBadCipher() in go1.8
- tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, // forbidden by http/2, not flagged by http2isBadCipher() in go1.8
- tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, // forbidden by http/2
- tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, // forbidden by http/2
- tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, // forbidden by http/2
- tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, // forbidden by http/2
- tls.TLS_RSA_WITH_AES_128_GCM_SHA256, // forbidden by http/2
- tls.TLS_RSA_WITH_AES_256_GCM_SHA384, // forbidden by http/2
- // the next one is in the intermediate suite, but go1.8 http2isBadCipher() complains when it is included at the recommended index
- // because it comes after ciphers forbidden by the http/2 spec
- // tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
- // tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, // forbidden by http/2, disabled to mitigate SWEET32 attack
- // tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA, // forbidden by http/2, disabled to mitigate SWEET32 attack
- tls.TLS_RSA_WITH_AES_128_CBC_SHA, // forbidden by http/2
- tls.TLS_RSA_WITH_AES_256_CBC_SHA, // forbidden by http/2
+
+ // TLS 1.3 cipher suites (negotiated automatically, not configurable)
tls.TLS_AES_128_GCM_SHA256,
tls.TLS_AES_256_GCM_SHA384,
tls.TLS_CHACHA20_POLY1305_SHA256,
diff --git a/etcd/vendor/github.com/spf13/cobra/.golangci.yml b/etcd/vendor/github.com/spf13/cobra/.golangci.yml
index 2c8f4808c1..6acf8ab1ea 100644
--- a/etcd/vendor/github.com/spf13/cobra/.golangci.yml
+++ b/etcd/vendor/github.com/spf13/cobra/.golangci.yml
@@ -12,14 +12,20 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+version: "2"
+
run:
- deadline: 5m
+ timeout: 5m
+
+formatters:
+ enable:
+ - gofmt
+ - goimports
linters:
- disable-all: true
+ default: none
enable:
#- bodyclose
- # - deadcode ! deprecated since v1.49.0; replaced by 'unused'
#- depguard
#- dogsled
#- dupl
@@ -30,28 +36,24 @@ linters:
- goconst
- gocritic
#- gocyclo
- - gofmt
- - goimports
- #- gomnd
#- goprintffuncname
- gosec
- - gosimple
- govet
- ineffassign
#- lll
- misspell
+ #- mnd
#- nakedret
#- noctx
- nolintlint
#- rowserrcheck
- #- scopelint
- staticcheck
- #- structcheck ! deprecated since v1.49.0; replaced by 'unused'
- - stylecheck
- #- typecheck
- unconvert
#- unparam
- unused
- # - varcheck ! deprecated since v1.49.0; replaced by 'unused'
#- whitespace
- fast: false
+ exclusions:
+ presets:
+ - common-false-positives
+ - legacy
+ - std-error-handling
diff --git a/etcd/vendor/github.com/spf13/cobra/README.md b/etcd/vendor/github.com/spf13/cobra/README.md
index 71757151c3..8416275f48 100644
--- a/etcd/vendor/github.com/spf13/cobra/README.md
+++ b/etcd/vendor/github.com/spf13/cobra/README.md
@@ -1,8 +1,14 @@
-
-
+
Cobra is a library for creating powerful modern CLI applications.
+Visit Cobra.dev for extensive documentation
+
+
Cobra is used in many Go projects such as [Kubernetes](https://kubernetes.io/),
[Hugo](https://gohugo.io), and [GitHub CLI](https://github.com/cli/cli) to
name a few. [This list](site/content/projects_using_cobra.md) contains a more extensive list of projects using Cobra.
@@ -11,6 +17,20 @@ name a few. [This list](site/content/projects_using_cobra.md) contains a more ex
[](https://pkg.go.dev/github.com/spf13/cobra)
[](https://goreportcard.com/report/github.com/spf13/cobra)
[](https://gophers.slack.com/archives/CD3LP1199)
+
+
+
Supported by:
+
+
+
+
+
+
+### [Warp, the AI terminal for devs](https://www.warp.dev/cobra)
+[Try Cobra in Warp today](https://www.warp.dev/cobra)
+
+
+
# Overview
diff --git a/etcd/vendor/github.com/spf13/cobra/SECURITY.md b/etcd/vendor/github.com/spf13/cobra/SECURITY.md
new file mode 100644
index 0000000000..54e60c28c1
--- /dev/null
+++ b/etcd/vendor/github.com/spf13/cobra/SECURITY.md
@@ -0,0 +1,105 @@
+# Security Policy
+
+## Reporting a Vulnerability
+
+The `cobra` maintainers take security issues seriously and
+we appreciate your efforts to _**responsibly**_ disclose your findings.
+We will make every effort to swiftly respond and address concerns.
+
+To report a security vulnerability:
+
+1. **DO NOT** create a public GitHub issue for the vulnerability!
+2. **DO NOT** create a public GitHub Pull Request with a fix for the vulnerability!
+3. Send an email to `cobra-security@googlegroups.com`.
+4. Include the following details in your report:
+ - Description of the vulnerability
+ - Steps to reproduce
+ - Potential impact of the vulnerability (to your downstream project, to the Go ecosystem, etc.)
+ - Any potential mitigations you've already identified
+5. Allow up to 7 days for an initial response.
+ You should receive an acknowledgment of your report and an estimated timeline for a fix.
+6. (Optional) If you have a fix and would like to contribute your patch, please work
+ directly with the maintainers via `cobra-security@googlegroups.com` to
+ coordinate pushing the patch to GitHub, cutting a new release, and disclosing the change.
+
+## Response Process
+
+When a security vulnerability report is received, the `cobra` maintainers will:
+
+1. Confirm receipt of the vulnerability report within 7 days.
+2. Assess the report to determine if it constitutes a security vulnerability.
+3. If confirmed, assign the vulnerability a severity level and create a timeline for addressing it.
+4. Develop and test a fix.
+5. Patch the vulnerability and make a new GitHub release: the maintainers will coordinate disclosure with the reporter.
+6. Create a new GitHub Security Advisory to inform the broader Go ecosystem
+
+## Disclosure Policy
+
+The `cobra` maintainers follow a coordinated disclosure process:
+
+1. Security vulnerabilities will be addressed as quickly as possible.
+2. A CVE (Common Vulnerabilities and Exposures) identifier will be requested for significant vulnerabilities
+ that are within `cobra` itself.
+3. Once a fix is ready, the maintainers will:
+ - Release a new version containing the fix.
+ - Update the security advisory with details about the vulnerability.
+ - Credit the reporter (unless they wish to remain anonymous).
+ - Credit the fixer (unless they wish to remain anonymous, this may be the same as the reporter).
+ - Announce the vulnerability through appropriate channels
+ (GitHub Security Advisory, mailing lists, GitHub Releases, etc.)
+
+## Supported Versions
+
+Security fixes will typically only be released for the most recent major release.
+
+## Upstream Security Issues
+
+`cobra` generally will not accept vulnerability reports that originate in upstream
+dependencies. I.e., if there is a problem in Go code that `cobra` depends on,
+it is best to engage that project's maintainers and owners.
+
+This security policy primarily pertains only to `cobra` itself but if you believe you've
+identified a problem that originates in an upstream dependency and is being widely
+distributed by `cobra`, please follow the disclosure procedure above: the `cobra`
+maintainers will work with you to determine the severity and ecosystem impact.
+
+## Security Updates and CVEs
+
+Information about known security vulnerabilities and CVEs affecting `cobra` will
+be published as GitHub Security Advisories at
+https://github.com/spf13/cobra/security/advisories.
+
+All users are encouraged to watch the repository and upgrade promptly when
+security releases are published.
+
+## `cobra` Security Best Practices for Users
+
+When using `cobra` in your CLIs, the `cobra` maintainers recommend the following:
+
+1. Always use the latest version of `cobra`.
+2. [Use Go modules](https://go.dev/blog/using-go-modules) for dependency management.
+3. Always use the latest possible version of Go.
+
+## Security Best Practices for Contributors
+
+When contributing to `cobra`:
+
+1. Be mindful of security implications when adding new features or modifying existing ones.
+2. Be aware of `cobra`'s extremely large reach: it is used in nearly every Go CLI
+ (like Kubernetes, Docker, Prometheus, etc. etc.)
+3. Write tests that explicitly cover edge cases and potential issues.
+4. If you discover a security issue while working on `cobra`, please report it
+ following the process above rather than opening a public pull request or issue that
+ addresses the vulnerability.
+5. Take personal sec-ops seriously and secure your GitHub account: use [two-factor authentication](https://docs.github.com/en/authentication/securing-your-account-with-two-factor-authentication-2fa),
+ [sign your commits with a GPG or SSH key](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification),
+ etc.
+
+## Acknowledgments
+
+The `cobra` maintainers would like to thank all security researchers and
+community members who help keep cobra, its users, and the entire Go ecosystem secure through responsible disclosures!!
+
+---
+
+*This security policy is inspired by the [Open Web Application Security Project (OWASP)](https://owasp.org/) guidelines and security best practices.*
diff --git a/etcd/vendor/github.com/spf13/cobra/command.go b/etcd/vendor/github.com/spf13/cobra/command.go
index dbb2c298ba..78088db69c 100644
--- a/etcd/vendor/github.com/spf13/cobra/command.go
+++ b/etcd/vendor/github.com/spf13/cobra/command.go
@@ -39,7 +39,7 @@ const (
)
// FParseErrWhitelist configures Flag parse errors to be ignored
-type FParseErrWhitelist flag.ParseErrorsWhitelist
+type FParseErrWhitelist flag.ParseErrorsAllowlist
// Group Structure to manage groups for commands
type Group struct {
@@ -1296,6 +1296,11 @@ Simply type ` + c.DisplayName() + ` help [path to command] for full details.`,
c.Printf("Unknown help topic %#q\n", args)
CheckErr(c.Root().Usage())
} else {
+ // FLow the context down to be used in help text
+ if cmd.ctx == nil {
+ cmd.ctx = c.ctx
+ }
+
cmd.InitDefaultHelpFlag() // make possible 'help' flag to be shown
cmd.InitDefaultVersionFlag() // make possible 'version' flag to be shown
CheckErr(cmd.Help())
@@ -1872,7 +1877,7 @@ func (c *Command) ParseFlags(args []string) error {
c.mergePersistentFlags()
// do it here after merging all flags and just before parse
- c.Flags().ParseErrorsWhitelist = flag.ParseErrorsWhitelist(c.FParseErrWhitelist)
+ c.Flags().ParseErrorsAllowlist = flag.ParseErrorsAllowlist(c.FParseErrWhitelist)
err := c.Flags().Parse(args)
// Print warnings if they occurred (e.g. deprecated flag messages).
@@ -2020,7 +2025,7 @@ func defaultUsageFunc(w io.Writer, in interface{}) error {
fmt.Fprint(w, trimRightSpace(c.InheritedFlags().FlagUsages()))
}
if c.HasHelpSubCommands() {
- fmt.Fprintf(w, "\n\nAdditional help topcis:")
+ fmt.Fprintf(w, "\n\nAdditional help topics:")
for _, subcmd := range c.Commands() {
if subcmd.IsAdditionalHelpTopicCommand() {
fmt.Fprintf(w, "\n %s %s", rpad(subcmd.CommandPath(), subcmd.CommandPathPadding()), subcmd.Short)
diff --git a/etcd/vendor/github.com/spf13/cobra/completions.go b/etcd/vendor/github.com/spf13/cobra/completions.go
index a1752f7631..d3607c2d2f 100644
--- a/etcd/vendor/github.com/spf13/cobra/completions.go
+++ b/etcd/vendor/github.com/spf13/cobra/completions.go
@@ -115,6 +115,13 @@ type CompletionOptions struct {
DisableDescriptions bool
// HiddenDefaultCmd makes the default 'completion' command hidden
HiddenDefaultCmd bool
+ // DefaultShellCompDirective sets the ShellCompDirective that is returned
+ // if no special directive can be determined
+ DefaultShellCompDirective *ShellCompDirective
+}
+
+func (receiver *CompletionOptions) SetDefaultShellCompDirective(directive ShellCompDirective) {
+ receiver.DefaultShellCompDirective = &directive
}
// Completion is a string that can be used for completions
@@ -375,7 +382,7 @@ func (c *Command) getCompletions(args []string) (*Command, []Completion, ShellCo
// Error while attempting to parse flags
if flagErr != nil {
// If error type is flagCompError and we don't want flagCompletion we should ignore the error
- if _, ok := flagErr.(*flagCompError); !(ok && !flagCompletion) {
+ if _, ok := flagErr.(*flagCompError); !ok || flagCompletion {
return finalCmd, []Completion{}, ShellCompDirectiveDefault, flagErr
}
}
@@ -480,6 +487,14 @@ func (c *Command) getCompletions(args []string) (*Command, []Completion, ShellCo
}
} else {
directive = ShellCompDirectiveDefault
+ // check current and parent commands for a custom DefaultShellCompDirective
+ for cmd := finalCmd; cmd != nil; cmd = cmd.parent {
+ if cmd.CompletionOptions.DefaultShellCompDirective != nil {
+ directive = *cmd.CompletionOptions.DefaultShellCompDirective
+ break
+ }
+ }
+
if flag == nil {
foundLocalNonPersistentFlag := false
// If TraverseChildren is true on the root command we don't check for
@@ -773,7 +788,7 @@ See each sub-command's help for details on how to use the generated script.
// shell completion for it (prog __complete completion '')
subCmd, cmdArgs, err := c.Find(args)
if err != nil || subCmd.Name() != compCmdName &&
- !(subCmd.Name() == ShellCompRequestCmd && len(cmdArgs) > 1 && cmdArgs[0] == compCmdName) {
+ (subCmd.Name() != ShellCompRequestCmd || len(cmdArgs) <= 1 || cmdArgs[0] != compCmdName) {
// The completion command is not being called or being completed so we remove it.
c.RemoveCommand(completionCmd)
return
diff --git a/etcd/vendor/golang.org/x/net/context/context.go b/etcd/vendor/golang.org/x/net/context/context.go
index db1c95fab1..24cea68820 100644
--- a/etcd/vendor/golang.org/x/net/context/context.go
+++ b/etcd/vendor/golang.org/x/net/context/context.go
@@ -2,44 +2,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Package context defines the Context type, which carries deadlines,
-// cancellation signals, and other request-scoped values across API boundaries
-// and between processes.
-// As of Go 1.7 this package is available in the standard library under the
-// name [context], and migrating to it can be done automatically with [go fix].
-//
-// Incoming requests to a server should create a [Context], and outgoing
-// calls to servers should accept a Context. The chain of function
-// calls between them must propagate the Context, optionally replacing
-// it with a derived Context created using [WithCancel], [WithDeadline],
-// [WithTimeout], or [WithValue].
-//
-// Programs that use Contexts should follow these rules to keep interfaces
-// consistent across packages and enable static analysis tools to check context
-// propagation:
-//
-// Do not store Contexts inside a struct type; instead, pass a Context
-// explicitly to each function that needs it. This is discussed further in
-// https://go.dev/blog/context-and-structs. The Context should be the first
-// parameter, typically named ctx:
-//
-// func DoSomething(ctx context.Context, arg Arg) error {
-// // ... use ctx ...
-// }
-//
-// Do not pass a nil [Context], even if a function permits it. Pass [context.TODO]
-// if you are unsure about which Context to use.
-//
-// Use context Values only for request-scoped data that transits processes and
-// APIs, not for passing optional parameters to functions.
+// Package context has been superseded by the standard library [context] package.
//
-// The same Context may be passed to functions running in different goroutines;
-// Contexts are safe for simultaneous use by multiple goroutines.
-//
-// See https://go.dev/blog/context for example code for a server that uses
-// Contexts.
-//
-// [go fix]: https://go.dev/cmd/go#hdr-Update_packages_to_use_new_APIs
+// Deprecated: Use the standard library context package instead.
package context
import (
@@ -51,36 +16,37 @@ import (
// API boundaries.
//
// Context's methods may be called by multiple goroutines simultaneously.
+//
+//go:fix inline
type Context = context.Context
// Canceled is the error returned by [Context.Err] when the context is canceled
// for some reason other than its deadline passing.
+//
+//go:fix inline
var Canceled = context.Canceled
// DeadlineExceeded is the error returned by [Context.Err] when the context is canceled
// due to its deadline passing.
+//
+//go:fix inline
var DeadlineExceeded = context.DeadlineExceeded
// Background returns a non-nil, empty Context. It is never canceled, has no
// values, and has no deadline. It is typically used by the main function,
// initialization, and tests, and as the top-level Context for incoming
// requests.
-func Background() Context {
- return background
-}
+//
+//go:fix inline
+func Background() Context { return context.Background() }
// TODO returns a non-nil, empty Context. Code should use context.TODO when
// it's unclear which Context to use or it is not yet available (because the
// surrounding function has not yet been extended to accept a Context
// parameter).
-func TODO() Context {
- return todo
-}
-
-var (
- background = context.Background()
- todo = context.TODO()
-)
+//
+//go:fix inline
+func TODO() Context { return context.TODO() }
// A CancelFunc tells an operation to abandon its work.
// A CancelFunc does not wait for the work to stop.
@@ -95,6 +61,8 @@ type CancelFunc = context.CancelFunc
//
// Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this [Context] complete.
+//
+//go:fix inline
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
return context.WithCancel(parent)
}
@@ -108,6 +76,8 @@ func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
//
// Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this [Context] complete.
+//
+//go:fix inline
func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {
return context.WithDeadline(parent, d)
}
@@ -122,6 +92,8 @@ func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {
// defer cancel() // releases resources if slowOperation completes before timeout elapses
// return slowOperation(ctx)
// }
+//
+//go:fix inline
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
return context.WithTimeout(parent, timeout)
}
@@ -139,6 +111,8 @@ func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
// interface{}, context keys often have concrete type
// struct{}. Alternatively, exported context key variables' static
// type should be a pointer or interface.
+//
+//go:fix inline
func WithValue(parent Context, key, val interface{}) Context {
return context.WithValue(parent, key, val)
}
diff --git a/etcd/vendor/golang.org/x/net/html/escape.go b/etcd/vendor/golang.org/x/net/html/escape.go
index 04c6bec210..12f2273706 100644
--- a/etcd/vendor/golang.org/x/net/html/escape.go
+++ b/etcd/vendor/golang.org/x/net/html/escape.go
@@ -299,7 +299,7 @@ func escape(w writer, s string) error {
case '\r':
esc = "
"
default:
- panic("unrecognized escape character")
+ panic("html: unrecognized escape character")
}
s = s[i+1:]
if _, err := w.WriteString(esc); err != nil {
diff --git a/etcd/vendor/golang.org/x/net/html/parse.go b/etcd/vendor/golang.org/x/net/html/parse.go
index 518ee4c94e..88fc0056a3 100644
--- a/etcd/vendor/golang.org/x/net/html/parse.go
+++ b/etcd/vendor/golang.org/x/net/html/parse.go
@@ -136,7 +136,7 @@ func (p *parser) indexOfElementInScope(s scope, matchTags ...a.Atom) int {
return -1
}
default:
- panic("unreachable")
+ panic(fmt.Sprintf("html: internal error: indexOfElementInScope unknown scope: %d", s))
}
}
switch s {
@@ -179,7 +179,7 @@ func (p *parser) clearStackToContext(s scope) {
return
}
default:
- panic("unreachable")
+ panic(fmt.Sprintf("html: internal error: clearStackToContext unknown scope: %d", s))
}
}
}
@@ -231,7 +231,14 @@ func (p *parser) addChild(n *Node) {
}
if n.Type == ElementNode {
- p.oe = append(p.oe, n)
+ p.insertOpenElement(n)
+ }
+}
+
+func (p *parser) insertOpenElement(n *Node) {
+ p.oe = append(p.oe, n)
+ if len(p.oe) > 512 {
+ panic("html: open stack of elements exceeds 512 nodes")
}
}
@@ -810,7 +817,7 @@ func afterHeadIM(p *parser) bool {
p.im = inFramesetIM
return true
case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title:
- p.oe = append(p.oe, p.head)
+ p.insertOpenElement(p.head)
defer p.oe.remove(p.head)
return inHeadIM(p)
case a.Head:
@@ -1678,7 +1685,7 @@ func inTableBodyIM(p *parser) bool {
return inTableIM(p)
}
-// Section 12.2.6.4.14.
+// Section 13.2.6.4.14.
func inRowIM(p *parser) bool {
switch p.tok.Type {
case StartTagToken:
@@ -1690,7 +1697,9 @@ func inRowIM(p *parser) bool {
p.im = inCellIM
return true
case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Tfoot, a.Thead, a.Tr:
- if p.popUntil(tableScope, a.Tr) {
+ if p.elementInScope(tableScope, a.Tr) {
+ p.clearStackToContext(tableRowScope)
+ p.oe.pop()
p.im = inTableBodyIM
return false
}
@@ -1700,22 +1709,28 @@ func inRowIM(p *parser) bool {
case EndTagToken:
switch p.tok.DataAtom {
case a.Tr:
- if p.popUntil(tableScope, a.Tr) {
+ if p.elementInScope(tableScope, a.Tr) {
+ p.clearStackToContext(tableRowScope)
+ p.oe.pop()
p.im = inTableBodyIM
return true
}
// Ignore the token.
return true
case a.Table:
- if p.popUntil(tableScope, a.Tr) {
+ if p.elementInScope(tableScope, a.Tr) {
+ p.clearStackToContext(tableRowScope)
+ p.oe.pop()
p.im = inTableBodyIM
return false
}
// Ignore the token.
return true
case a.Tbody, a.Tfoot, a.Thead:
- if p.elementInScope(tableScope, p.tok.DataAtom) {
- p.parseImpliedToken(EndTagToken, a.Tr, a.Tr.String())
+ if p.elementInScope(tableScope, p.tok.DataAtom) && p.elementInScope(tableScope, a.Tr) {
+ p.clearStackToContext(tableRowScope)
+ p.oe.pop()
+ p.im = inTableBodyIM
return false
}
// Ignore the token.
@@ -2222,16 +2237,20 @@ func parseForeignContent(p *parser) bool {
p.acknowledgeSelfClosingTag()
}
case EndTagToken:
+ if strings.EqualFold(p.oe[len(p.oe)-1].Data, p.tok.Data) {
+ p.oe = p.oe[:len(p.oe)-1]
+ return true
+ }
for i := len(p.oe) - 1; i >= 0; i-- {
- if p.oe[i].Namespace == "" {
- return p.im(p)
- }
if strings.EqualFold(p.oe[i].Data, p.tok.Data) {
p.oe = p.oe[:i]
+ return true
+ }
+ if i > 0 && p.oe[i-1].Namespace == "" {
break
}
}
- return true
+ return p.im(p)
default:
// Ignore the token.
}
@@ -2312,9 +2331,13 @@ func (p *parser) parseCurrentToken() {
}
}
-func (p *parser) parse() error {
+func (p *parser) parse() (err error) {
+ defer func() {
+ if panicErr := recover(); panicErr != nil {
+ err = fmt.Errorf("%s", panicErr)
+ }
+ }()
// Iterate until EOF. Any other error will cause an early return.
- var err error
for err != io.EOF {
// CDATA sections are allowed only in foreign content.
n := p.oe.top()
@@ -2343,6 +2366,8 @@ func (p *parser) parse() error {
// s. Conversely, explicit s in r's data can be silently dropped,
// with no corresponding node in the resulting tree.
//
+// Parse will reject HTML that is nested deeper than 512 elements.
+//
// The input is assumed to be UTF-8 encoded.
func Parse(r io.Reader) (*Node, error) {
return ParseWithOptions(r)
diff --git a/etcd/vendor/golang.org/x/net/html/render.go b/etcd/vendor/golang.org/x/net/html/render.go
index e8c1233455..0157d89e1f 100644
--- a/etcd/vendor/golang.org/x/net/html/render.go
+++ b/etcd/vendor/golang.org/x/net/html/render.go
@@ -184,7 +184,7 @@ func render1(w writer, n *Node) error {
return err
}
- // Add initial newline where there is danger of a newline beging ignored.
+ // Add initial newline where there is danger of a newline being ignored.
if c := n.FirstChild; c != nil && c.Type == TextNode && strings.HasPrefix(c.Data, "\n") {
switch n.Data {
case "pre", "listing", "textarea":
diff --git a/etcd/vendor/golang.org/x/net/http2/config.go b/etcd/vendor/golang.org/x/net/http2/config.go
index ca645d9a1a..8a7a89d016 100644
--- a/etcd/vendor/golang.org/x/net/http2/config.go
+++ b/etcd/vendor/golang.org/x/net/http2/config.go
@@ -27,6 +27,7 @@ import (
// - If the resulting value is zero or out of range, use a default.
type http2Config struct {
MaxConcurrentStreams uint32
+ StrictMaxConcurrentRequests bool
MaxDecoderHeaderTableSize uint32
MaxEncoderHeaderTableSize uint32
MaxReadFrameSize uint32
@@ -55,7 +56,7 @@ func configFromServer(h1 *http.Server, h2 *Server) http2Config {
PermitProhibitedCipherSuites: h2.PermitProhibitedCipherSuites,
CountError: h2.CountError,
}
- fillNetHTTPServerConfig(&conf, h1)
+ fillNetHTTPConfig(&conf, h1.HTTP2)
setConfigDefaults(&conf, true)
return conf
}
@@ -64,12 +65,13 @@ func configFromServer(h1 *http.Server, h2 *Server) http2Config {
// (the net/http Transport).
func configFromTransport(h2 *Transport) http2Config {
conf := http2Config{
- MaxEncoderHeaderTableSize: h2.MaxEncoderHeaderTableSize,
- MaxDecoderHeaderTableSize: h2.MaxDecoderHeaderTableSize,
- MaxReadFrameSize: h2.MaxReadFrameSize,
- SendPingTimeout: h2.ReadIdleTimeout,
- PingTimeout: h2.PingTimeout,
- WriteByteTimeout: h2.WriteByteTimeout,
+ StrictMaxConcurrentRequests: h2.StrictMaxConcurrentStreams,
+ MaxEncoderHeaderTableSize: h2.MaxEncoderHeaderTableSize,
+ MaxDecoderHeaderTableSize: h2.MaxDecoderHeaderTableSize,
+ MaxReadFrameSize: h2.MaxReadFrameSize,
+ SendPingTimeout: h2.ReadIdleTimeout,
+ PingTimeout: h2.PingTimeout,
+ WriteByteTimeout: h2.WriteByteTimeout,
}
// Unlike most config fields, where out-of-range values revert to the default,
@@ -81,7 +83,7 @@ func configFromTransport(h2 *Transport) http2Config {
}
if h2.t1 != nil {
- fillNetHTTPTransportConfig(&conf, h2.t1)
+ fillNetHTTPConfig(&conf, h2.t1.HTTP2)
}
setConfigDefaults(&conf, false)
return conf
@@ -120,3 +122,48 @@ func adjustHTTP1MaxHeaderSize(n int64) int64 {
const typicalHeaders = 10 // conservative
return n + typicalHeaders*perFieldOverhead
}
+
+func fillNetHTTPConfig(conf *http2Config, h2 *http.HTTP2Config) {
+ if h2 == nil {
+ return
+ }
+ if h2.MaxConcurrentStreams != 0 {
+ conf.MaxConcurrentStreams = uint32(h2.MaxConcurrentStreams)
+ }
+ if http2ConfigStrictMaxConcurrentRequests(h2) {
+ conf.StrictMaxConcurrentRequests = true
+ }
+ if h2.MaxEncoderHeaderTableSize != 0 {
+ conf.MaxEncoderHeaderTableSize = uint32(h2.MaxEncoderHeaderTableSize)
+ }
+ if h2.MaxDecoderHeaderTableSize != 0 {
+ conf.MaxDecoderHeaderTableSize = uint32(h2.MaxDecoderHeaderTableSize)
+ }
+ if h2.MaxConcurrentStreams != 0 {
+ conf.MaxConcurrentStreams = uint32(h2.MaxConcurrentStreams)
+ }
+ if h2.MaxReadFrameSize != 0 {
+ conf.MaxReadFrameSize = uint32(h2.MaxReadFrameSize)
+ }
+ if h2.MaxReceiveBufferPerConnection != 0 {
+ conf.MaxUploadBufferPerConnection = int32(h2.MaxReceiveBufferPerConnection)
+ }
+ if h2.MaxReceiveBufferPerStream != 0 {
+ conf.MaxUploadBufferPerStream = int32(h2.MaxReceiveBufferPerStream)
+ }
+ if h2.SendPingTimeout != 0 {
+ conf.SendPingTimeout = h2.SendPingTimeout
+ }
+ if h2.PingTimeout != 0 {
+ conf.PingTimeout = h2.PingTimeout
+ }
+ if h2.WriteByteTimeout != 0 {
+ conf.WriteByteTimeout = h2.WriteByteTimeout
+ }
+ if h2.PermitProhibitedCipherSuites {
+ conf.PermitProhibitedCipherSuites = true
+ }
+ if h2.CountError != nil {
+ conf.CountError = h2.CountError
+ }
+}
diff --git a/etcd/vendor/golang.org/x/net/http2/config_go124.go b/etcd/vendor/golang.org/x/net/http2/config_go124.go
deleted file mode 100644
index 5b516c55ff..0000000000
--- a/etcd/vendor/golang.org/x/net/http2/config_go124.go
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2024 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.24
-
-package http2
-
-import "net/http"
-
-// fillNetHTTPServerConfig sets fields in conf from srv.HTTP2.
-func fillNetHTTPServerConfig(conf *http2Config, srv *http.Server) {
- fillNetHTTPConfig(conf, srv.HTTP2)
-}
-
-// fillNetHTTPTransportConfig sets fields in conf from tr.HTTP2.
-func fillNetHTTPTransportConfig(conf *http2Config, tr *http.Transport) {
- fillNetHTTPConfig(conf, tr.HTTP2)
-}
-
-func fillNetHTTPConfig(conf *http2Config, h2 *http.HTTP2Config) {
- if h2 == nil {
- return
- }
- if h2.MaxConcurrentStreams != 0 {
- conf.MaxConcurrentStreams = uint32(h2.MaxConcurrentStreams)
- }
- if h2.MaxEncoderHeaderTableSize != 0 {
- conf.MaxEncoderHeaderTableSize = uint32(h2.MaxEncoderHeaderTableSize)
- }
- if h2.MaxDecoderHeaderTableSize != 0 {
- conf.MaxDecoderHeaderTableSize = uint32(h2.MaxDecoderHeaderTableSize)
- }
- if h2.MaxConcurrentStreams != 0 {
- conf.MaxConcurrentStreams = uint32(h2.MaxConcurrentStreams)
- }
- if h2.MaxReadFrameSize != 0 {
- conf.MaxReadFrameSize = uint32(h2.MaxReadFrameSize)
- }
- if h2.MaxReceiveBufferPerConnection != 0 {
- conf.MaxUploadBufferPerConnection = int32(h2.MaxReceiveBufferPerConnection)
- }
- if h2.MaxReceiveBufferPerStream != 0 {
- conf.MaxUploadBufferPerStream = int32(h2.MaxReceiveBufferPerStream)
- }
- if h2.SendPingTimeout != 0 {
- conf.SendPingTimeout = h2.SendPingTimeout
- }
- if h2.PingTimeout != 0 {
- conf.PingTimeout = h2.PingTimeout
- }
- if h2.WriteByteTimeout != 0 {
- conf.WriteByteTimeout = h2.WriteByteTimeout
- }
- if h2.PermitProhibitedCipherSuites {
- conf.PermitProhibitedCipherSuites = true
- }
- if h2.CountError != nil {
- conf.CountError = h2.CountError
- }
-}
diff --git a/etcd/vendor/golang.org/x/net/http2/config_go125.go b/etcd/vendor/golang.org/x/net/http2/config_go125.go
new file mode 100644
index 0000000000..b4373fe33c
--- /dev/null
+++ b/etcd/vendor/golang.org/x/net/http2/config_go125.go
@@ -0,0 +1,15 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !go1.26
+
+package http2
+
+import (
+ "net/http"
+)
+
+func http2ConfigStrictMaxConcurrentRequests(h2 *http.HTTP2Config) bool {
+ return false
+}
diff --git a/etcd/vendor/golang.org/x/net/http2/config_go126.go b/etcd/vendor/golang.org/x/net/http2/config_go126.go
new file mode 100644
index 0000000000..6b071c149d
--- /dev/null
+++ b/etcd/vendor/golang.org/x/net/http2/config_go126.go
@@ -0,0 +1,15 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build go1.26
+
+package http2
+
+import (
+ "net/http"
+)
+
+func http2ConfigStrictMaxConcurrentRequests(h2 *http.HTTP2Config) bool {
+ return h2.StrictMaxConcurrentRequests
+}
diff --git a/etcd/vendor/golang.org/x/net/http2/config_pre_go124.go b/etcd/vendor/golang.org/x/net/http2/config_pre_go124.go
deleted file mode 100644
index 060fd6c64c..0000000000
--- a/etcd/vendor/golang.org/x/net/http2/config_pre_go124.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2024 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.24
-
-package http2
-
-import "net/http"
-
-// Pre-Go 1.24 fallback.
-// The Server.HTTP2 and Transport.HTTP2 config fields were added in Go 1.24.
-
-func fillNetHTTPServerConfig(conf *http2Config, srv *http.Server) {}
-
-func fillNetHTTPTransportConfig(conf *http2Config, tr *http.Transport) {}
diff --git a/etcd/vendor/golang.org/x/net/http2/frame.go b/etcd/vendor/golang.org/x/net/http2/frame.go
index db3264da8c..9a4bd123c9 100644
--- a/etcd/vendor/golang.org/x/net/http2/frame.go
+++ b/etcd/vendor/golang.org/x/net/http2/frame.go
@@ -280,6 +280,8 @@ type Framer struct {
// lastHeaderStream is non-zero if the last frame was an
// unfinished HEADERS/CONTINUATION.
lastHeaderStream uint32
+ // lastFrameType holds the type of the last frame for verifying frame order.
+ lastFrameType FrameType
maxReadSize uint32
headerBuf [frameHeaderLen]byte
@@ -347,7 +349,7 @@ func (fr *Framer) maxHeaderListSize() uint32 {
func (f *Framer) startWrite(ftype FrameType, flags Flags, streamID uint32) {
// Write the FrameHeader.
f.wbuf = append(f.wbuf[:0],
- 0, // 3 bytes of length, filled in in endWrite
+ 0, // 3 bytes of length, filled in endWrite
0,
0,
byte(ftype),
@@ -488,30 +490,41 @@ func terminalReadFrameError(err error) bool {
return err != nil
}
-// ReadFrame reads a single frame. The returned Frame is only valid
-// until the next call to ReadFrame.
+// ReadFrameHeader reads the header of the next frame.
+// It reads the 9-byte fixed frame header, and does not read any portion of the
+// frame payload. The caller is responsible for consuming the payload, either
+// with ReadFrameForHeader or directly from the Framer's io.Reader.
//
-// If the frame is larger than previously set with SetMaxReadFrameSize, the
-// returned error is ErrFrameTooLarge. Other errors may be of type
-// ConnectionError, StreamError, or anything else from the underlying
-// reader.
+// If the frame is larger than previously set with SetMaxReadFrameSize, it
+// returns the frame header and ErrFrameTooLarge.
//
-// If ReadFrame returns an error and a non-nil Frame, the Frame's StreamID
-// indicates the stream responsible for the error.
-func (fr *Framer) ReadFrame() (Frame, error) {
+// If the returned FrameHeader.StreamID is non-zero, it indicates the stream
+// responsible for the error.
+func (fr *Framer) ReadFrameHeader() (FrameHeader, error) {
fr.errDetail = nil
- if fr.lastFrame != nil {
- fr.lastFrame.invalidate()
- }
fh, err := readFrameHeader(fr.headerBuf[:], fr.r)
if err != nil {
- return nil, err
+ return fh, err
}
if fh.Length > fr.maxReadSize {
if fh == invalidHTTP1LookingFrameHeader() {
- return nil, fmt.Errorf("http2: failed reading the frame payload: %w, note that the frame header looked like an HTTP/1.1 header", ErrFrameTooLarge)
+ return fh, fmt.Errorf("http2: failed reading the frame payload: %w, note that the frame header looked like an HTTP/1.1 header", ErrFrameTooLarge)
}
- return nil, ErrFrameTooLarge
+ return fh, ErrFrameTooLarge
+ }
+ if err := fr.checkFrameOrder(fh); err != nil {
+ return fh, err
+ }
+ return fh, nil
+}
+
+// ReadFrameForHeader reads the payload for the frame with the given FrameHeader.
+//
+// It behaves identically to ReadFrame, other than not checking the maximum
+// frame size.
+func (fr *Framer) ReadFrameForHeader(fh FrameHeader) (Frame, error) {
+ if fr.lastFrame != nil {
+ fr.lastFrame.invalidate()
}
payload := fr.getReadBuf(fh.Length)
if _, err := io.ReadFull(fr.r, payload); err != nil {
@@ -527,9 +540,7 @@ func (fr *Framer) ReadFrame() (Frame, error) {
}
return nil, err
}
- if err := fr.checkFrameOrder(f); err != nil {
- return nil, err
- }
+ fr.lastFrame = f
if fr.logReads {
fr.debugReadLoggerf("http2: Framer %p: read %v", fr, summarizeFrame(f))
}
@@ -539,6 +550,24 @@ func (fr *Framer) ReadFrame() (Frame, error) {
return f, nil
}
+// ReadFrame reads a single frame. The returned Frame is only valid
+// until the next call to ReadFrame or ReadFrameBodyForHeader.
+//
+// If the frame is larger than previously set with SetMaxReadFrameSize, the
+// returned error is ErrFrameTooLarge. Other errors may be of type
+// ConnectionError, StreamError, or anything else from the underlying
+// reader.
+//
+// If ReadFrame returns an error and a non-nil Frame, the Frame's StreamID
+// indicates the stream responsible for the error.
+func (fr *Framer) ReadFrame() (Frame, error) {
+ fh, err := fr.ReadFrameHeader()
+ if err != nil {
+ return nil, err
+ }
+ return fr.ReadFrameForHeader(fh)
+}
+
// connError returns ConnectionError(code) but first
// stashes away a public reason to the caller can optionally relay it
// to the peer before hanging up on them. This might help others debug
@@ -551,20 +580,19 @@ func (fr *Framer) connError(code ErrCode, reason string) error {
// checkFrameOrder reports an error if f is an invalid frame to return
// next from ReadFrame. Mostly it checks whether HEADERS and
// CONTINUATION frames are contiguous.
-func (fr *Framer) checkFrameOrder(f Frame) error {
- last := fr.lastFrame
- fr.lastFrame = f
+func (fr *Framer) checkFrameOrder(fh FrameHeader) error {
+ lastType := fr.lastFrameType
+ fr.lastFrameType = fh.Type
if fr.AllowIllegalReads {
return nil
}
- fh := f.Header()
if fr.lastHeaderStream != 0 {
if fh.Type != FrameContinuation {
return fr.connError(ErrCodeProtocol,
fmt.Sprintf("got %s for stream %d; expected CONTINUATION following %s for stream %d",
fh.Type, fh.StreamID,
- last.Header().Type, fr.lastHeaderStream))
+ lastType, fr.lastHeaderStream))
}
if fh.StreamID != fr.lastHeaderStream {
return fr.connError(ErrCodeProtocol,
@@ -1152,7 +1180,16 @@ type PriorityFrame struct {
PriorityParam
}
-// PriorityParam are the stream prioritzation parameters.
+var defaultRFC9218Priority = PriorityParam{
+ incremental: 0,
+ urgency: 3,
+}
+
+// Note that HTTP/2 has had two different prioritization schemes, and
+// PriorityParam struct below is a superset of both schemes. The exported
+// symbols are from RFC 7540 and the non-exported ones are from RFC 9218.
+
+// PriorityParam are the stream prioritization parameters.
type PriorityParam struct {
// StreamDep is a 31-bit stream identifier for the
// stream that this stream depends on. Zero means no
@@ -1167,6 +1204,20 @@ type PriorityParam struct {
// the spec, "Add one to the value to obtain a weight between
// 1 and 256."
Weight uint8
+
+ // "The urgency (u) parameter value is Integer (see Section 3.3.1 of
+ // [STRUCTURED-FIELDS]), between 0 and 7 inclusive, in descending order of
+ // priority. The default is 3."
+ urgency uint8
+
+ // "The incremental (i) parameter value is Boolean (see Section 3.3.6 of
+ // [STRUCTURED-FIELDS]). It indicates if an HTTP response can be processed
+ // incrementally, i.e., provide some meaningful output as chunks of the
+ // response arrive."
+ //
+ // We use uint8 (i.e. 0 is false, 1 is true) instead of bool so we can
+ // avoid unnecessary type conversions and because either type takes 1 byte.
+ incremental uint8
}
func (p PriorityParam) IsZero() bool {
diff --git a/etcd/vendor/golang.org/x/net/http2/gotrack.go b/etcd/vendor/golang.org/x/net/http2/gotrack.go
index 9933c9f8c7..9921ca096d 100644
--- a/etcd/vendor/golang.org/x/net/http2/gotrack.go
+++ b/etcd/vendor/golang.org/x/net/http2/gotrack.go
@@ -15,21 +15,32 @@ import (
"runtime"
"strconv"
"sync"
+ "sync/atomic"
)
var DebugGoroutines = os.Getenv("DEBUG_HTTP2_GOROUTINES") == "1"
+// Setting DebugGoroutines to false during a test to disable goroutine debugging
+// results in race detector complaints when a test leaves goroutines running before
+// returning. Tests shouldn't do this, of course, but when they do it generally shows
+// up as infrequent, hard-to-debug flakes. (See #66519.)
+//
+// Disable goroutine debugging during individual tests with an atomic bool.
+// (Note that it's safe to enable/disable debugging mid-test, so the actual race condition
+// here is harmless.)
+var disableDebugGoroutines atomic.Bool
+
type goroutineLock uint64
func newGoroutineLock() goroutineLock {
- if !DebugGoroutines {
+ if !DebugGoroutines || disableDebugGoroutines.Load() {
return 0
}
return goroutineLock(curGoroutineID())
}
func (g goroutineLock) check() {
- if !DebugGoroutines {
+ if !DebugGoroutines || disableDebugGoroutines.Load() {
return
}
if curGoroutineID() != uint64(g) {
@@ -38,7 +49,7 @@ func (g goroutineLock) check() {
}
func (g goroutineLock) checkNotOn() {
- if !DebugGoroutines {
+ if !DebugGoroutines || disableDebugGoroutines.Load() {
return
}
if curGoroutineID() == uint64(g) {
diff --git a/etcd/vendor/golang.org/x/net/http2/http2.go b/etcd/vendor/golang.org/x/net/http2/http2.go
index ea5ae629fd..105fe12fef 100644
--- a/etcd/vendor/golang.org/x/net/http2/http2.go
+++ b/etcd/vendor/golang.org/x/net/http2/http2.go
@@ -15,7 +15,6 @@ package http2 // import "golang.org/x/net/http2"
import (
"bufio"
- "context"
"crypto/tls"
"errors"
"fmt"
@@ -35,7 +34,6 @@ var (
VerboseLogs bool
logFrameWrites bool
logFrameReads bool
- inTests bool
// Enabling extended CONNECT by causes browsers to attempt to use
// WebSockets-over-HTTP/2. This results in problems when the server's websocket
@@ -255,15 +253,13 @@ func (cw closeWaiter) Wait() {
// idle memory usage with many connections.
type bufferedWriter struct {
_ incomparable
- group synctestGroupInterface // immutable
- conn net.Conn // immutable
- bw *bufio.Writer // non-nil when data is buffered
- byteTimeout time.Duration // immutable, WriteByteTimeout
+ conn net.Conn // immutable
+ bw *bufio.Writer // non-nil when data is buffered
+ byteTimeout time.Duration // immutable, WriteByteTimeout
}
-func newBufferedWriter(group synctestGroupInterface, conn net.Conn, timeout time.Duration) *bufferedWriter {
+func newBufferedWriter(conn net.Conn, timeout time.Duration) *bufferedWriter {
return &bufferedWriter{
- group: group,
conn: conn,
byteTimeout: timeout,
}
@@ -314,24 +310,18 @@ func (w *bufferedWriter) Flush() error {
type bufferedWriterTimeoutWriter bufferedWriter
func (w *bufferedWriterTimeoutWriter) Write(p []byte) (n int, err error) {
- return writeWithByteTimeout(w.group, w.conn, w.byteTimeout, p)
+ return writeWithByteTimeout(w.conn, w.byteTimeout, p)
}
// writeWithByteTimeout writes to conn.
// If more than timeout passes without any bytes being written to the connection,
// the write fails.
-func writeWithByteTimeout(group synctestGroupInterface, conn net.Conn, timeout time.Duration, p []byte) (n int, err error) {
+func writeWithByteTimeout(conn net.Conn, timeout time.Duration, p []byte) (n int, err error) {
if timeout <= 0 {
return conn.Write(p)
}
for {
- var now time.Time
- if group == nil {
- now = time.Now()
- } else {
- now = group.Now()
- }
- conn.SetWriteDeadline(now.Add(timeout))
+ conn.SetWriteDeadline(time.Now().Add(timeout))
nn, err := conn.Write(p[n:])
n += nn
if n == len(p) || nn == 0 || !errors.Is(err, os.ErrDeadlineExceeded) {
@@ -417,14 +407,3 @@ func (s *sorter) SortStrings(ss []string) {
// makes that struct also non-comparable, and generally doesn't add
// any size (as long as it's first).
type incomparable [0]func()
-
-// synctestGroupInterface is the methods of synctestGroup used by Server and Transport.
-// It's defined as an interface here to let us keep synctestGroup entirely test-only
-// and not a part of non-test builds.
-type synctestGroupInterface interface {
- Join()
- Now() time.Time
- NewTimer(d time.Duration) timer
- AfterFunc(d time.Duration, f func()) timer
- ContextWithTimeout(ctx context.Context, d time.Duration) (context.Context, context.CancelFunc)
-}
diff --git a/etcd/vendor/golang.org/x/net/http2/server.go b/etcd/vendor/golang.org/x/net/http2/server.go
index 51fca38f61..bdc5520ebd 100644
--- a/etcd/vendor/golang.org/x/net/http2/server.go
+++ b/etcd/vendor/golang.org/x/net/http2/server.go
@@ -176,44 +176,15 @@ type Server struct {
// so that we don't embed a Mutex in this struct, which will make the
// struct non-copyable, which might break some callers.
state *serverInternalState
-
- // Synchronization group used for testing.
- // Outside of tests, this is nil.
- group synctestGroupInterface
-}
-
-func (s *Server) markNewGoroutine() {
- if s.group != nil {
- s.group.Join()
- }
-}
-
-func (s *Server) now() time.Time {
- if s.group != nil {
- return s.group.Now()
- }
- return time.Now()
-}
-
-// newTimer creates a new time.Timer, or a synthetic timer in tests.
-func (s *Server) newTimer(d time.Duration) timer {
- if s.group != nil {
- return s.group.NewTimer(d)
- }
- return timeTimer{time.NewTimer(d)}
-}
-
-// afterFunc creates a new time.AfterFunc timer, or a synthetic timer in tests.
-func (s *Server) afterFunc(d time.Duration, f func()) timer {
- if s.group != nil {
- return s.group.AfterFunc(d, f)
- }
- return timeTimer{time.AfterFunc(d, f)}
}
type serverInternalState struct {
mu sync.Mutex
activeConns map[*serverConn]struct{}
+
+ // Pool of error channels. This is per-Server rather than global
+ // because channels can't be reused across synctest bubbles.
+ errChanPool sync.Pool
}
func (s *serverInternalState) registerConn(sc *serverConn) {
@@ -245,6 +216,27 @@ func (s *serverInternalState) startGracefulShutdown() {
s.mu.Unlock()
}
+// Global error channel pool used for uninitialized Servers.
+// We use a per-Server pool when possible to avoid using channels across synctest bubbles.
+var errChanPool = sync.Pool{
+ New: func() any { return make(chan error, 1) },
+}
+
+func (s *serverInternalState) getErrChan() chan error {
+ if s == nil {
+ return errChanPool.Get().(chan error) // Server used without calling ConfigureServer
+ }
+ return s.errChanPool.Get().(chan error)
+}
+
+func (s *serverInternalState) putErrChan(ch chan error) {
+ if s == nil {
+ errChanPool.Put(ch) // Server used without calling ConfigureServer
+ return
+ }
+ s.errChanPool.Put(ch)
+}
+
// ConfigureServer adds HTTP/2 support to a net/http Server.
//
// The configuration conf may be nil.
@@ -257,7 +249,10 @@ func ConfigureServer(s *http.Server, conf *Server) error {
if conf == nil {
conf = new(Server)
}
- conf.state = &serverInternalState{activeConns: make(map[*serverConn]struct{})}
+ conf.state = &serverInternalState{
+ activeConns: make(map[*serverConn]struct{}),
+ errChanPool: sync.Pool{New: func() any { return make(chan error, 1) }},
+ }
if h1, h2 := s, conf; h2.IdleTimeout == 0 {
if h1.IdleTimeout != 0 {
h2.IdleTimeout = h1.IdleTimeout
@@ -423,6 +418,9 @@ func (o *ServeConnOpts) handler() http.Handler {
//
// The opts parameter is optional. If nil, default values are used.
func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
+ if opts == nil {
+ opts = &ServeConnOpts{}
+ }
s.serveConn(c, opts, nil)
}
@@ -438,7 +436,7 @@ func (s *Server) serveConn(c net.Conn, opts *ServeConnOpts, newf func(*serverCon
conn: c,
baseCtx: baseCtx,
remoteAddrStr: c.RemoteAddr().String(),
- bw: newBufferedWriter(s.group, c, conf.WriteByteTimeout),
+ bw: newBufferedWriter(c, conf.WriteByteTimeout),
handler: opts.handler(),
streams: make(map[uint32]*stream),
readFrameCh: make(chan readFrameResult),
@@ -638,11 +636,11 @@ type serverConn struct {
pingSent bool
sentPingData [8]byte
goAwayCode ErrCode
- shutdownTimer timer // nil until used
- idleTimer timer // nil if unused
+ shutdownTimer *time.Timer // nil until used
+ idleTimer *time.Timer // nil if unused
readIdleTimeout time.Duration
pingTimeout time.Duration
- readIdleTimer timer // nil if unused
+ readIdleTimer *time.Timer // nil if unused
// Owned by the writeFrameAsync goroutine:
headerWriteBuf bytes.Buffer
@@ -687,12 +685,12 @@ type stream struct {
flow outflow // limits writing from Handler to client
inflow inflow // what the client is allowed to POST/etc to us
state streamState
- resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
- gotTrailerHeader bool // HEADER frame for trailers was seen
- wroteHeaders bool // whether we wrote headers (not status 100)
- readDeadline timer // nil if unused
- writeDeadline timer // nil if unused
- closeErr error // set before cw is closed
+ resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
+ gotTrailerHeader bool // HEADER frame for trailers was seen
+ wroteHeaders bool // whether we wrote headers (not status 100)
+ readDeadline *time.Timer // nil if unused
+ writeDeadline *time.Timer // nil if unused
+ closeErr error // set before cw is closed
trailer http.Header // accumulated trailers
reqTrailer http.Header // handler's Request.Trailer
@@ -848,7 +846,6 @@ type readFrameResult struct {
// consumer is done with the frame.
// It's run on its own goroutine.
func (sc *serverConn) readFrames() {
- sc.srv.markNewGoroutine()
gate := make(chan struct{})
gateDone := func() { gate <- struct{}{} }
for {
@@ -881,7 +878,6 @@ type frameWriteResult struct {
// At most one goroutine can be running writeFrameAsync at a time per
// serverConn.
func (sc *serverConn) writeFrameAsync(wr FrameWriteRequest, wd *writeData) {
- sc.srv.markNewGoroutine()
var err error
if wd == nil {
err = wr.write.writeFrame(sc)
@@ -965,22 +961,22 @@ func (sc *serverConn) serve(conf http2Config) {
sc.setConnState(http.StateIdle)
if sc.srv.IdleTimeout > 0 {
- sc.idleTimer = sc.srv.afterFunc(sc.srv.IdleTimeout, sc.onIdleTimer)
+ sc.idleTimer = time.AfterFunc(sc.srv.IdleTimeout, sc.onIdleTimer)
defer sc.idleTimer.Stop()
}
if conf.SendPingTimeout > 0 {
sc.readIdleTimeout = conf.SendPingTimeout
- sc.readIdleTimer = sc.srv.afterFunc(conf.SendPingTimeout, sc.onReadIdleTimer)
+ sc.readIdleTimer = time.AfterFunc(conf.SendPingTimeout, sc.onReadIdleTimer)
defer sc.readIdleTimer.Stop()
}
go sc.readFrames() // closed by defer sc.conn.Close above
- settingsTimer := sc.srv.afterFunc(firstSettingsTimeout, sc.onSettingsTimer)
+ settingsTimer := time.AfterFunc(firstSettingsTimeout, sc.onSettingsTimer)
defer settingsTimer.Stop()
- lastFrameTime := sc.srv.now()
+ lastFrameTime := time.Now()
loopNum := 0
for {
loopNum++
@@ -994,7 +990,7 @@ func (sc *serverConn) serve(conf http2Config) {
case res := <-sc.wroteFrameCh:
sc.wroteFrame(res)
case res := <-sc.readFrameCh:
- lastFrameTime = sc.srv.now()
+ lastFrameTime = time.Now()
// Process any written frames before reading new frames from the client since a
// written frame could have triggered a new stream to be started.
if sc.writingFrameAsync {
@@ -1077,7 +1073,7 @@ func (sc *serverConn) handlePingTimer(lastFrameReadTime time.Time) {
}
pingAt := lastFrameReadTime.Add(sc.readIdleTimeout)
- now := sc.srv.now()
+ now := time.Now()
if pingAt.After(now) {
// We received frames since arming the ping timer.
// Reset it for the next possible timeout.
@@ -1141,10 +1137,10 @@ func (sc *serverConn) readPreface() error {
errc <- nil
}
}()
- timer := sc.srv.newTimer(prefaceTimeout) // TODO: configurable on *Server?
+ timer := time.NewTimer(prefaceTimeout) // TODO: configurable on *Server?
defer timer.Stop()
select {
- case <-timer.C():
+ case <-timer.C:
return errPrefaceTimeout
case err := <-errc:
if err == nil {
@@ -1156,10 +1152,6 @@ func (sc *serverConn) readPreface() error {
}
}
-var errChanPool = sync.Pool{
- New: func() interface{} { return make(chan error, 1) },
-}
-
var writeDataPool = sync.Pool{
New: func() interface{} { return new(writeData) },
}
@@ -1167,7 +1159,7 @@ var writeDataPool = sync.Pool{
// writeDataFromHandler writes DATA response frames from a handler on
// the given stream.
func (sc *serverConn) writeDataFromHandler(stream *stream, data []byte, endStream bool) error {
- ch := errChanPool.Get().(chan error)
+ ch := sc.srv.state.getErrChan()
writeArg := writeDataPool.Get().(*writeData)
*writeArg = writeData{stream.id, data, endStream}
err := sc.writeFrameFromHandler(FrameWriteRequest{
@@ -1199,7 +1191,7 @@ func (sc *serverConn) writeDataFromHandler(stream *stream, data []byte, endStrea
return errStreamClosed
}
}
- errChanPool.Put(ch)
+ sc.srv.state.putErrChan(ch)
if frameWriteDone {
writeDataPool.Put(writeArg)
}
@@ -1513,7 +1505,7 @@ func (sc *serverConn) goAway(code ErrCode) {
func (sc *serverConn) shutDownIn(d time.Duration) {
sc.serveG.check()
- sc.shutdownTimer = sc.srv.afterFunc(d, sc.onShutdownTimer)
+ sc.shutdownTimer = time.AfterFunc(d, sc.onShutdownTimer)
}
func (sc *serverConn) resetStream(se StreamError) {
@@ -2118,7 +2110,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
// (in Go 1.8), though. That's a more sane option anyway.
if sc.hs.ReadTimeout > 0 {
sc.conn.SetReadDeadline(time.Time{})
- st.readDeadline = sc.srv.afterFunc(sc.hs.ReadTimeout, st.onReadTimeout)
+ st.readDeadline = time.AfterFunc(sc.hs.ReadTimeout, st.onReadTimeout)
}
return sc.scheduleHandler(id, rw, req, handler)
@@ -2216,7 +2208,7 @@ func (sc *serverConn) newStream(id, pusherID uint32, state streamState) *stream
st.flow.add(sc.initialStreamSendWindowSize)
st.inflow.init(sc.initialStreamRecvWindowSize)
if sc.hs.WriteTimeout > 0 {
- st.writeDeadline = sc.srv.afterFunc(sc.hs.WriteTimeout, st.onWriteTimeout)
+ st.writeDeadline = time.AfterFunc(sc.hs.WriteTimeout, st.onWriteTimeout)
}
sc.streams[id] = st
@@ -2405,7 +2397,6 @@ func (sc *serverConn) handlerDone() {
// Run on its own goroutine.
func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) {
- sc.srv.markNewGoroutine()
defer sc.sendServeMsg(handlerDoneMsg)
didPanic := true
defer func() {
@@ -2454,7 +2445,7 @@ func (sc *serverConn) writeHeaders(st *stream, headerData *writeResHeaders) erro
// waiting for this frame to be written, so an http.Flush mid-handler
// writes out the correct value of keys, before a handler later potentially
// mutates it.
- errc = errChanPool.Get().(chan error)
+ errc = sc.srv.state.getErrChan()
}
if err := sc.writeFrameFromHandler(FrameWriteRequest{
write: headerData,
@@ -2466,7 +2457,7 @@ func (sc *serverConn) writeHeaders(st *stream, headerData *writeResHeaders) erro
if errc != nil {
select {
case err := <-errc:
- errChanPool.Put(errc)
+ sc.srv.state.putErrChan(errc)
return err
case <-sc.doneServing:
return errClientDisconnected
@@ -2573,7 +2564,7 @@ func (b *requestBody) Read(p []byte) (n int, err error) {
if err == io.EOF {
b.sawEOF = true
}
- if b.conn == nil && inTests {
+ if b.conn == nil {
return
}
b.conn.noteBodyReadFromHandler(b.stream, n, err)
@@ -2702,7 +2693,7 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
var date string
if _, ok := rws.snapHeader["Date"]; !ok {
// TODO(bradfitz): be faster here, like net/http? measure.
- date = rws.conn.srv.now().UTC().Format(http.TimeFormat)
+ date = time.Now().UTC().Format(http.TimeFormat)
}
for _, v := range rws.snapHeader["Trailer"] {
@@ -2824,7 +2815,7 @@ func (rws *responseWriterState) promoteUndeclaredTrailers() {
func (w *responseWriter) SetReadDeadline(deadline time.Time) error {
st := w.rws.stream
- if !deadline.IsZero() && deadline.Before(w.rws.conn.srv.now()) {
+ if !deadline.IsZero() && deadline.Before(time.Now()) {
// If we're setting a deadline in the past, reset the stream immediately
// so writes after SetWriteDeadline returns will fail.
st.onReadTimeout()
@@ -2840,9 +2831,9 @@ func (w *responseWriter) SetReadDeadline(deadline time.Time) error {
if deadline.IsZero() {
st.readDeadline = nil
} else if st.readDeadline == nil {
- st.readDeadline = sc.srv.afterFunc(deadline.Sub(sc.srv.now()), st.onReadTimeout)
+ st.readDeadline = time.AfterFunc(deadline.Sub(time.Now()), st.onReadTimeout)
} else {
- st.readDeadline.Reset(deadline.Sub(sc.srv.now()))
+ st.readDeadline.Reset(deadline.Sub(time.Now()))
}
})
return nil
@@ -2850,7 +2841,7 @@ func (w *responseWriter) SetReadDeadline(deadline time.Time) error {
func (w *responseWriter) SetWriteDeadline(deadline time.Time) error {
st := w.rws.stream
- if !deadline.IsZero() && deadline.Before(w.rws.conn.srv.now()) {
+ if !deadline.IsZero() && deadline.Before(time.Now()) {
// If we're setting a deadline in the past, reset the stream immediately
// so writes after SetWriteDeadline returns will fail.
st.onWriteTimeout()
@@ -2866,9 +2857,9 @@ func (w *responseWriter) SetWriteDeadline(deadline time.Time) error {
if deadline.IsZero() {
st.writeDeadline = nil
} else if st.writeDeadline == nil {
- st.writeDeadline = sc.srv.afterFunc(deadline.Sub(sc.srv.now()), st.onWriteTimeout)
+ st.writeDeadline = time.AfterFunc(deadline.Sub(time.Now()), st.onWriteTimeout)
} else {
- st.writeDeadline.Reset(deadline.Sub(sc.srv.now()))
+ st.writeDeadline.Reset(deadline.Sub(time.Now()))
}
})
return nil
@@ -3147,7 +3138,7 @@ func (w *responseWriter) Push(target string, opts *http.PushOptions) error {
method: opts.Method,
url: u,
header: cloneHeader(opts.Header),
- done: errChanPool.Get().(chan error),
+ done: sc.srv.state.getErrChan(),
}
select {
@@ -3164,7 +3155,7 @@ func (w *responseWriter) Push(target string, opts *http.PushOptions) error {
case <-st.cw:
return errStreamClosed
case err := <-msg.done:
- errChanPool.Put(msg.done)
+ sc.srv.state.putErrChan(msg.done)
return err
}
}
diff --git a/etcd/vendor/golang.org/x/net/http2/timer.go b/etcd/vendor/golang.org/x/net/http2/timer.go
deleted file mode 100644
index 0b1c17b812..0000000000
--- a/etcd/vendor/golang.org/x/net/http2/timer.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2024 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-package http2
-
-import "time"
-
-// A timer is a time.Timer, as an interface which can be replaced in tests.
-type timer = interface {
- C() <-chan time.Time
- Reset(d time.Duration) bool
- Stop() bool
-}
-
-// timeTimer adapts a time.Timer to the timer interface.
-type timeTimer struct {
- *time.Timer
-}
-
-func (t timeTimer) C() <-chan time.Time { return t.Timer.C }
diff --git a/etcd/vendor/golang.org/x/net/http2/transport.go b/etcd/vendor/golang.org/x/net/http2/transport.go
index f26356b9cd..1965913e54 100644
--- a/etcd/vendor/golang.org/x/net/http2/transport.go
+++ b/etcd/vendor/golang.org/x/net/http2/transport.go
@@ -9,6 +9,7 @@ package http2
import (
"bufio"
"bytes"
+ "compress/flate"
"compress/gzip"
"context"
"crypto/rand"
@@ -193,50 +194,6 @@ type Transport struct {
type transportTestHooks struct {
newclientconn func(*ClientConn)
- group synctestGroupInterface
-}
-
-func (t *Transport) markNewGoroutine() {
- if t != nil && t.transportTestHooks != nil {
- t.transportTestHooks.group.Join()
- }
-}
-
-func (t *Transport) now() time.Time {
- if t != nil && t.transportTestHooks != nil {
- return t.transportTestHooks.group.Now()
- }
- return time.Now()
-}
-
-func (t *Transport) timeSince(when time.Time) time.Duration {
- if t != nil && t.transportTestHooks != nil {
- return t.now().Sub(when)
- }
- return time.Since(when)
-}
-
-// newTimer creates a new time.Timer, or a synthetic timer in tests.
-func (t *Transport) newTimer(d time.Duration) timer {
- if t.transportTestHooks != nil {
- return t.transportTestHooks.group.NewTimer(d)
- }
- return timeTimer{time.NewTimer(d)}
-}
-
-// afterFunc creates a new time.AfterFunc timer, or a synthetic timer in tests.
-func (t *Transport) afterFunc(d time.Duration, f func()) timer {
- if t.transportTestHooks != nil {
- return t.transportTestHooks.group.AfterFunc(d, f)
- }
- return timeTimer{time.AfterFunc(d, f)}
-}
-
-func (t *Transport) contextWithTimeout(ctx context.Context, d time.Duration) (context.Context, context.CancelFunc) {
- if t.transportTestHooks != nil {
- return t.transportTestHooks.group.ContextWithTimeout(ctx, d)
- }
- return context.WithTimeout(ctx, d)
}
func (t *Transport) maxHeaderListSize() uint32 {
@@ -366,7 +323,7 @@ type ClientConn struct {
readerErr error // set before readerDone is closed
idleTimeout time.Duration // or 0 for never
- idleTimer timer
+ idleTimer *time.Timer
mu sync.Mutex // guards following
cond *sync.Cond // hold mu; broadcast on flow/closed changes
@@ -399,6 +356,7 @@ type ClientConn struct {
readIdleTimeout time.Duration
pingTimeout time.Duration
extendedConnectAllowed bool
+ strictMaxConcurrentStreams bool
// rstStreamPingsBlocked works around an unfortunate gRPC behavior.
// gRPC strictly limits the number of PING frames that it will receive.
@@ -534,14 +492,12 @@ func (cs *clientStream) closeReqBodyLocked() {
cs.reqBodyClosed = make(chan struct{})
reqBodyClosed := cs.reqBodyClosed
go func() {
- cs.cc.t.markNewGoroutine()
cs.reqBody.Close()
close(reqBodyClosed)
}()
}
type stickyErrWriter struct {
- group synctestGroupInterface
conn net.Conn
timeout time.Duration
err *error
@@ -551,7 +507,7 @@ func (sew stickyErrWriter) Write(p []byte) (n int, err error) {
if *sew.err != nil {
return 0, *sew.err
}
- n, err = writeWithByteTimeout(sew.group, sew.conn, sew.timeout, p)
+ n, err = writeWithByteTimeout(sew.conn, sew.timeout, p)
*sew.err = err
return n, err
}
@@ -650,9 +606,9 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res
backoff := float64(uint(1) << (uint(retry) - 1))
backoff += backoff * (0.1 * mathrand.Float64())
d := time.Second * time.Duration(backoff)
- tm := t.newTimer(d)
+ tm := time.NewTimer(d)
select {
- case <-tm.C():
+ case <-tm.C:
t.vlogf("RoundTrip retrying after failure: %v", roundTripErr)
continue
case <-req.Context().Done():
@@ -699,6 +655,7 @@ var (
errClientConnUnusable = errors.New("http2: client conn not usable")
errClientConnNotEstablished = errors.New("http2: client conn could not be established")
errClientConnGotGoAway = errors.New("http2: Transport received Server's graceful shutdown GOAWAY")
+ errClientConnForceClosed = errors.New("http2: client connection force closed via ClientConn.Close")
)
// shouldRetryRequest is called by RoundTrip when a request fails to get
@@ -829,7 +786,8 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, erro
initialWindowSize: 65535, // spec default
initialStreamRecvWindowSize: conf.MaxUploadBufferPerStream,
maxConcurrentStreams: initialMaxConcurrentStreams, // "infinite", per spec. Use a smaller value until we have received server settings.
- peerMaxHeaderListSize: 0xffffffffffffffff, // "infinite", per spec. Use 2^64-1 instead.
+ strictMaxConcurrentStreams: conf.StrictMaxConcurrentRequests,
+ peerMaxHeaderListSize: 0xffffffffffffffff, // "infinite", per spec. Use 2^64-1 instead.
streams: make(map[uint32]*clientStream),
singleUse: singleUse,
seenSettingsChan: make(chan struct{}),
@@ -838,14 +796,11 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, erro
pingTimeout: conf.PingTimeout,
pings: make(map[[8]byte]chan struct{}),
reqHeaderMu: make(chan struct{}, 1),
- lastActive: t.now(),
+ lastActive: time.Now(),
}
- var group synctestGroupInterface
if t.transportTestHooks != nil {
- t.markNewGoroutine()
t.transportTestHooks.newclientconn(cc)
c = cc.tconn
- group = t.group
}
if VerboseLogs {
t.vlogf("http2: Transport creating client conn %p to %v", cc, c.RemoteAddr())
@@ -857,7 +812,6 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, erro
// TODO: adjust this writer size to account for frame size +
// MTU + crypto/tls record padding.
cc.bw = bufio.NewWriter(stickyErrWriter{
- group: group,
conn: c,
timeout: conf.WriteByteTimeout,
err: &cc.werr,
@@ -906,7 +860,7 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, erro
// Start the idle timer after the connection is fully initialized.
if d := t.idleConnTimeout(); d != 0 {
cc.idleTimeout = d
- cc.idleTimer = t.afterFunc(d, cc.onIdleTimeout)
+ cc.idleTimer = time.AfterFunc(d, cc.onIdleTimeout)
}
go cc.readLoop()
@@ -917,7 +871,7 @@ func (cc *ClientConn) healthCheck() {
pingTimeout := cc.pingTimeout
// We don't need to periodically ping in the health check, because the readLoop of ClientConn will
// trigger the healthCheck again if there is no frame received.
- ctx, cancel := cc.t.contextWithTimeout(context.Background(), pingTimeout)
+ ctx, cancel := context.WithTimeout(context.Background(), pingTimeout)
defer cancel()
cc.vlogf("http2: Transport sending health check")
err := cc.Ping(ctx)
@@ -1067,7 +1021,7 @@ func (cc *ClientConn) idleStateLocked() (st clientConnIdleState) {
return
}
var maxConcurrentOkay bool
- if cc.t.StrictMaxConcurrentStreams {
+ if cc.strictMaxConcurrentStreams {
// We'll tell the caller we can take a new request to
// prevent the caller from dialing a new TCP
// connection, but then we'll block later before
@@ -1120,7 +1074,7 @@ func (cc *ClientConn) tooIdleLocked() bool {
// times are compared based on their wall time. We don't want
// to reuse a connection that's been sitting idle during
// VM/laptop suspend if monotonic time was also frozen.
- return cc.idleTimeout != 0 && !cc.lastIdle.IsZero() && cc.t.timeSince(cc.lastIdle.Round(0)) > cc.idleTimeout
+ return cc.idleTimeout != 0 && !cc.lastIdle.IsZero() && time.Since(cc.lastIdle.Round(0)) > cc.idleTimeout
}
// onIdleTimeout is called from a time.AfterFunc goroutine. It will
@@ -1186,7 +1140,6 @@ func (cc *ClientConn) Shutdown(ctx context.Context) error {
done := make(chan struct{})
cancelled := false // guarded by cc.mu
go func() {
- cc.t.markNewGoroutine()
cc.mu.Lock()
defer cc.mu.Unlock()
for {
@@ -1257,8 +1210,7 @@ func (cc *ClientConn) closeForError(err error) {
//
// In-flight requests are interrupted. For a graceful shutdown, use Shutdown instead.
func (cc *ClientConn) Close() error {
- err := errors.New("http2: client connection force closed via ClientConn.Close")
- cc.closeForError(err)
+ cc.closeForError(errClientConnForceClosed)
return nil
}
@@ -1427,7 +1379,6 @@ func (cc *ClientConn) roundTrip(req *http.Request, streamf func(*clientStream))
//
// It sends the request and performs post-request cleanup (closing Request.Body, etc.).
func (cs *clientStream) doRequest(req *http.Request, streamf func(*clientStream)) {
- cs.cc.t.markNewGoroutine()
err := cs.writeRequest(req, streamf)
cs.cleanupWriteRequest(err)
}
@@ -1558,9 +1509,9 @@ func (cs *clientStream) writeRequest(req *http.Request, streamf func(*clientStre
var respHeaderTimer <-chan time.Time
var respHeaderRecv chan struct{}
if d := cc.responseHeaderTimeout(); d != 0 {
- timer := cc.t.newTimer(d)
+ timer := time.NewTimer(d)
defer timer.Stop()
- respHeaderTimer = timer.C()
+ respHeaderTimer = timer.C
respHeaderRecv = cs.respHeaderRecv
}
// Wait until the peer half-closes its end of the stream,
@@ -1753,7 +1704,7 @@ func (cc *ClientConn) awaitOpenSlotForStreamLocked(cs *clientStream) error {
// Return a fatal error which aborts the retry loop.
return errClientConnNotEstablished
}
- cc.lastActive = cc.t.now()
+ cc.lastActive = time.Now()
if cc.closed || !cc.canTakeNewRequestLocked() {
return errClientConnUnusable
}
@@ -2092,10 +2043,10 @@ func (cc *ClientConn) forgetStreamID(id uint32) {
if len(cc.streams) != slen-1 {
panic("forgetting unknown stream id")
}
- cc.lastActive = cc.t.now()
+ cc.lastActive = time.Now()
if len(cc.streams) == 0 && cc.idleTimer != nil {
cc.idleTimer.Reset(cc.idleTimeout)
- cc.lastIdle = cc.t.now()
+ cc.lastIdle = time.Now()
}
// Wake up writeRequestBody via clientStream.awaitFlowControl and
// wake up RoundTrip if there is a pending request.
@@ -2121,7 +2072,6 @@ type clientConnReadLoop struct {
// readLoop runs in its own goroutine and reads and dispatches frames.
func (cc *ClientConn) readLoop() {
- cc.t.markNewGoroutine()
rl := &clientConnReadLoop{cc: cc}
defer rl.cleanup()
cc.readerErr = rl.run()
@@ -2188,9 +2138,9 @@ func (rl *clientConnReadLoop) cleanup() {
if cc.idleTimeout > 0 && unusedWaitTime > cc.idleTimeout {
unusedWaitTime = cc.idleTimeout
}
- idleTime := cc.t.now().Sub(cc.lastActive)
+ idleTime := time.Now().Sub(cc.lastActive)
if atomic.LoadUint32(&cc.atomicReused) == 0 && idleTime < unusedWaitTime && !cc.closedOnIdle {
- cc.idleTimer = cc.t.afterFunc(unusedWaitTime-idleTime, func() {
+ cc.idleTimer = time.AfterFunc(unusedWaitTime-idleTime, func() {
cc.t.connPool().MarkDead(cc)
})
} else {
@@ -2250,9 +2200,9 @@ func (rl *clientConnReadLoop) run() error {
cc := rl.cc
gotSettings := false
readIdleTimeout := cc.readIdleTimeout
- var t timer
+ var t *time.Timer
if readIdleTimeout != 0 {
- t = cc.t.afterFunc(readIdleTimeout, cc.healthCheck)
+ t = time.AfterFunc(readIdleTimeout, cc.healthCheck)
}
for {
f, err := cc.fr.ReadFrame()
@@ -2998,7 +2948,6 @@ func (cc *ClientConn) Ping(ctx context.Context) error {
var pingError error
errc := make(chan struct{})
go func() {
- cc.t.markNewGoroutine()
cc.wmu.Lock()
defer cc.wmu.Unlock()
if pingError = cc.fr.WritePing(false, p); pingError != nil {
@@ -3128,35 +3077,102 @@ type erringRoundTripper struct{ err error }
func (rt erringRoundTripper) RoundTripErr() error { return rt.err }
func (rt erringRoundTripper) RoundTrip(*http.Request) (*http.Response, error) { return nil, rt.err }
+var errConcurrentReadOnResBody = errors.New("http2: concurrent read on response body")
+
// gzipReader wraps a response body so it can lazily
-// call gzip.NewReader on the first call to Read
+// get gzip.Reader from the pool on the first call to Read.
+// After Close is called it puts gzip.Reader to the pool immediately
+// if there is no Read in progress or later when Read completes.
type gzipReader struct {
_ incomparable
body io.ReadCloser // underlying Response.Body
- zr *gzip.Reader // lazily-initialized gzip reader
- zerr error // sticky error
+ mu sync.Mutex // guards zr and zerr
+ zr *gzip.Reader // stores gzip reader from the pool between reads
+ zerr error // sticky gzip reader init error or sentinel value to detect concurrent read and read after close
}
-func (gz *gzipReader) Read(p []byte) (n int, err error) {
+type eofReader struct{}
+
+func (eofReader) Read([]byte) (int, error) { return 0, io.EOF }
+func (eofReader) ReadByte() (byte, error) { return 0, io.EOF }
+
+var gzipPool = sync.Pool{New: func() any { return new(gzip.Reader) }}
+
+// gzipPoolGet gets a gzip.Reader from the pool and resets it to read from r.
+func gzipPoolGet(r io.Reader) (*gzip.Reader, error) {
+ zr := gzipPool.Get().(*gzip.Reader)
+ if err := zr.Reset(r); err != nil {
+ gzipPoolPut(zr)
+ return nil, err
+ }
+ return zr, nil
+}
+
+// gzipPoolPut puts a gzip.Reader back into the pool.
+func gzipPoolPut(zr *gzip.Reader) {
+ // Reset will allocate bufio.Reader if we pass it anything
+ // other than a flate.Reader, so ensure that it's getting one.
+ var r flate.Reader = eofReader{}
+ zr.Reset(r)
+ gzipPool.Put(zr)
+}
+
+// acquire returns a gzip.Reader for reading response body.
+// The reader must be released after use.
+func (gz *gzipReader) acquire() (*gzip.Reader, error) {
+ gz.mu.Lock()
+ defer gz.mu.Unlock()
if gz.zerr != nil {
- return 0, gz.zerr
+ return nil, gz.zerr
}
if gz.zr == nil {
- gz.zr, err = gzip.NewReader(gz.body)
- if err != nil {
- gz.zerr = err
- return 0, err
+ gz.zr, gz.zerr = gzipPoolGet(gz.body)
+ if gz.zerr != nil {
+ return nil, gz.zerr
}
}
- return gz.zr.Read(p)
+ ret := gz.zr
+ gz.zr, gz.zerr = nil, errConcurrentReadOnResBody
+ return ret, nil
}
-func (gz *gzipReader) Close() error {
- if err := gz.body.Close(); err != nil {
- return err
+// release returns the gzip.Reader to the pool if Close was called during Read.
+func (gz *gzipReader) release(zr *gzip.Reader) {
+ gz.mu.Lock()
+ defer gz.mu.Unlock()
+ if gz.zerr == errConcurrentReadOnResBody {
+ gz.zr, gz.zerr = zr, nil
+ } else { // fs.ErrClosed
+ gzipPoolPut(zr)
+ }
+}
+
+// close returns the gzip.Reader to the pool immediately or
+// signals release to do so after Read completes.
+func (gz *gzipReader) close() {
+ gz.mu.Lock()
+ defer gz.mu.Unlock()
+ if gz.zerr == nil && gz.zr != nil {
+ gzipPoolPut(gz.zr)
+ gz.zr = nil
}
gz.zerr = fs.ErrClosed
- return nil
+}
+
+func (gz *gzipReader) Read(p []byte) (n int, err error) {
+ zr, err := gz.acquire()
+ if err != nil {
+ return 0, err
+ }
+ defer gz.release(zr)
+
+ return zr.Read(p)
+}
+
+func (gz *gzipReader) Close() error {
+ gz.close()
+
+ return gz.body.Close()
}
type errorReader struct{ err error }
@@ -3228,7 +3244,7 @@ func traceGotConn(req *http.Request, cc *ClientConn, reused bool) {
cc.mu.Lock()
ci.WasIdle = len(cc.streams) == 0 && reused
if ci.WasIdle && !cc.lastActive.IsZero() {
- ci.IdleTime = cc.t.timeSince(cc.lastActive)
+ ci.IdleTime = time.Since(cc.lastActive)
}
cc.mu.Unlock()
diff --git a/etcd/vendor/golang.org/x/net/http2/writesched.go b/etcd/vendor/golang.org/x/net/http2/writesched.go
index cc893adc29..7de27be525 100644
--- a/etcd/vendor/golang.org/x/net/http2/writesched.go
+++ b/etcd/vendor/golang.org/x/net/http2/writesched.go
@@ -42,6 +42,8 @@ type OpenStreamOptions struct {
// PusherID is zero if the stream was initiated by the client. Otherwise,
// PusherID names the stream that pushed the newly opened stream.
PusherID uint32
+ // priority is used to set the priority of the newly opened stream.
+ priority PriorityParam
}
// FrameWriteRequest is a request to write a frame.
@@ -183,45 +185,75 @@ func (wr *FrameWriteRequest) replyToWriter(err error) {
}
// writeQueue is used by implementations of WriteScheduler.
+//
+// Each writeQueue contains a queue of FrameWriteRequests, meant to store all
+// FrameWriteRequests associated with a given stream. This is implemented as a
+// two-stage queue: currQueue[currPos:] and nextQueue. Removing an item is done
+// by incrementing currPos of currQueue. Adding an item is done by appending it
+// to the nextQueue. If currQueue is empty when trying to remove an item, we
+// can swap currQueue and nextQueue to remedy the situation.
+// This two-stage queue is analogous to the use of two lists in Okasaki's
+// purely functional queue but without the overhead of reversing the list when
+// swapping stages.
+//
+// writeQueue also contains prev and next, this can be used by implementations
+// of WriteScheduler to construct data structures that represent the order of
+// writing between different streams (e.g. circular linked list).
type writeQueue struct {
- s []FrameWriteRequest
+ currQueue []FrameWriteRequest
+ nextQueue []FrameWriteRequest
+ currPos int
+
prev, next *writeQueue
}
-func (q *writeQueue) empty() bool { return len(q.s) == 0 }
+func (q *writeQueue) empty() bool {
+ return (len(q.currQueue) - q.currPos + len(q.nextQueue)) == 0
+}
func (q *writeQueue) push(wr FrameWriteRequest) {
- q.s = append(q.s, wr)
+ q.nextQueue = append(q.nextQueue, wr)
}
func (q *writeQueue) shift() FrameWriteRequest {
- if len(q.s) == 0 {
+ if q.empty() {
panic("invalid use of queue")
}
- wr := q.s[0]
- // TODO: less copy-happy queue.
- copy(q.s, q.s[1:])
- q.s[len(q.s)-1] = FrameWriteRequest{}
- q.s = q.s[:len(q.s)-1]
+ if q.currPos >= len(q.currQueue) {
+ q.currQueue, q.currPos, q.nextQueue = q.nextQueue, 0, q.currQueue[:0]
+ }
+ wr := q.currQueue[q.currPos]
+ q.currQueue[q.currPos] = FrameWriteRequest{}
+ q.currPos++
return wr
}
+func (q *writeQueue) peek() *FrameWriteRequest {
+ if q.currPos < len(q.currQueue) {
+ return &q.currQueue[q.currPos]
+ }
+ if len(q.nextQueue) > 0 {
+ return &q.nextQueue[0]
+ }
+ return nil
+}
+
// consume consumes up to n bytes from q.s[0]. If the frame is
// entirely consumed, it is removed from the queue. If the frame
// is partially consumed, the frame is kept with the consumed
// bytes removed. Returns true iff any bytes were consumed.
func (q *writeQueue) consume(n int32) (FrameWriteRequest, bool) {
- if len(q.s) == 0 {
+ if q.empty() {
return FrameWriteRequest{}, false
}
- consumed, rest, numresult := q.s[0].Consume(n)
+ consumed, rest, numresult := q.peek().Consume(n)
switch numresult {
case 0:
return FrameWriteRequest{}, false
case 1:
q.shift()
case 2:
- q.s[0] = rest
+ *q.peek() = rest
}
return consumed, true
}
@@ -230,10 +262,15 @@ type writeQueuePool []*writeQueue
// put inserts an unused writeQueue into the pool.
func (p *writeQueuePool) put(q *writeQueue) {
- for i := range q.s {
- q.s[i] = FrameWriteRequest{}
+ for i := range q.currQueue {
+ q.currQueue[i] = FrameWriteRequest{}
+ }
+ for i := range q.nextQueue {
+ q.nextQueue[i] = FrameWriteRequest{}
}
- q.s = q.s[:0]
+ q.currQueue = q.currQueue[:0]
+ q.nextQueue = q.nextQueue[:0]
+ q.currPos = 0
*p = append(*p, q)
}
diff --git a/vendor/golang.org/x/net/http2/writesched_priority.go b/etcd/vendor/golang.org/x/net/http2/writesched_priority_rfc7540.go
similarity index 77%
rename from vendor/golang.org/x/net/http2/writesched_priority.go
rename to etcd/vendor/golang.org/x/net/http2/writesched_priority_rfc7540.go
index f6783339d1..4e33c29a24 100644
--- a/vendor/golang.org/x/net/http2/writesched_priority.go
+++ b/etcd/vendor/golang.org/x/net/http2/writesched_priority_rfc7540.go
@@ -11,7 +11,7 @@ import (
)
// RFC 7540, Section 5.3.5: the default weight is 16.
-const priorityDefaultWeight = 15 // 16 = 15 + 1
+const priorityDefaultWeightRFC7540 = 15 // 16 = 15 + 1
// PriorityWriteSchedulerConfig configures a priorityWriteScheduler.
type PriorityWriteSchedulerConfig struct {
@@ -66,8 +66,8 @@ func NewPriorityWriteScheduler(cfg *PriorityWriteSchedulerConfig) WriteScheduler
}
}
- ws := &priorityWriteScheduler{
- nodes: make(map[uint32]*priorityNode),
+ ws := &priorityWriteSchedulerRFC7540{
+ nodes: make(map[uint32]*priorityNodeRFC7540),
maxClosedNodesInTree: cfg.MaxClosedNodesInTree,
maxIdleNodesInTree: cfg.MaxIdleNodesInTree,
enableWriteThrottle: cfg.ThrottleOutOfOrderWrites,
@@ -81,32 +81,32 @@ func NewPriorityWriteScheduler(cfg *PriorityWriteSchedulerConfig) WriteScheduler
return ws
}
-type priorityNodeState int
+type priorityNodeStateRFC7540 int
const (
- priorityNodeOpen priorityNodeState = iota
- priorityNodeClosed
- priorityNodeIdle
+ priorityNodeOpenRFC7540 priorityNodeStateRFC7540 = iota
+ priorityNodeClosedRFC7540
+ priorityNodeIdleRFC7540
)
-// priorityNode is a node in an HTTP/2 priority tree.
+// priorityNodeRFC7540 is a node in an HTTP/2 priority tree.
// Each node is associated with a single stream ID.
// See RFC 7540, Section 5.3.
-type priorityNode struct {
- q writeQueue // queue of pending frames to write
- id uint32 // id of the stream, or 0 for the root of the tree
- weight uint8 // the actual weight is weight+1, so the value is in [1,256]
- state priorityNodeState // open | closed | idle
- bytes int64 // number of bytes written by this node, or 0 if closed
- subtreeBytes int64 // sum(node.bytes) of all nodes in this subtree
+type priorityNodeRFC7540 struct {
+ q writeQueue // queue of pending frames to write
+ id uint32 // id of the stream, or 0 for the root of the tree
+ weight uint8 // the actual weight is weight+1, so the value is in [1,256]
+ state priorityNodeStateRFC7540 // open | closed | idle
+ bytes int64 // number of bytes written by this node, or 0 if closed
+ subtreeBytes int64 // sum(node.bytes) of all nodes in this subtree
// These links form the priority tree.
- parent *priorityNode
- kids *priorityNode // start of the kids list
- prev, next *priorityNode // doubly-linked list of siblings
+ parent *priorityNodeRFC7540
+ kids *priorityNodeRFC7540 // start of the kids list
+ prev, next *priorityNodeRFC7540 // doubly-linked list of siblings
}
-func (n *priorityNode) setParent(parent *priorityNode) {
+func (n *priorityNodeRFC7540) setParent(parent *priorityNodeRFC7540) {
if n == parent {
panic("setParent to self")
}
@@ -141,7 +141,7 @@ func (n *priorityNode) setParent(parent *priorityNode) {
}
}
-func (n *priorityNode) addBytes(b int64) {
+func (n *priorityNodeRFC7540) addBytes(b int64) {
n.bytes += b
for ; n != nil; n = n.parent {
n.subtreeBytes += b
@@ -154,7 +154,7 @@ func (n *priorityNode) addBytes(b int64) {
//
// f(n, openParent) takes two arguments: the node to visit, n, and a bool that is true
// if any ancestor p of n is still open (ignoring the root node).
-func (n *priorityNode) walkReadyInOrder(openParent bool, tmp *[]*priorityNode, f func(*priorityNode, bool) bool) bool {
+func (n *priorityNodeRFC7540) walkReadyInOrder(openParent bool, tmp *[]*priorityNodeRFC7540, f func(*priorityNodeRFC7540, bool) bool) bool {
if !n.q.empty() && f(n, openParent) {
return true
}
@@ -165,7 +165,7 @@ func (n *priorityNode) walkReadyInOrder(openParent bool, tmp *[]*priorityNode, f
// Don't consider the root "open" when updating openParent since
// we can't send data frames on the root stream (only control frames).
if n.id != 0 {
- openParent = openParent || (n.state == priorityNodeOpen)
+ openParent = openParent || (n.state == priorityNodeOpenRFC7540)
}
// Common case: only one kid or all kids have the same weight.
@@ -195,7 +195,7 @@ func (n *priorityNode) walkReadyInOrder(openParent bool, tmp *[]*priorityNode, f
*tmp = append(*tmp, n.kids)
n.kids.setParent(nil)
}
- sort.Sort(sortPriorityNodeSiblings(*tmp))
+ sort.Sort(sortPriorityNodeSiblingsRFC7540(*tmp))
for i := len(*tmp) - 1; i >= 0; i-- {
(*tmp)[i].setParent(n) // setParent inserts at the head of n.kids
}
@@ -207,15 +207,15 @@ func (n *priorityNode) walkReadyInOrder(openParent bool, tmp *[]*priorityNode, f
return false
}
-type sortPriorityNodeSiblings []*priorityNode
+type sortPriorityNodeSiblingsRFC7540 []*priorityNodeRFC7540
-func (z sortPriorityNodeSiblings) Len() int { return len(z) }
-func (z sortPriorityNodeSiblings) Swap(i, k int) { z[i], z[k] = z[k], z[i] }
-func (z sortPriorityNodeSiblings) Less(i, k int) bool {
+func (z sortPriorityNodeSiblingsRFC7540) Len() int { return len(z) }
+func (z sortPriorityNodeSiblingsRFC7540) Swap(i, k int) { z[i], z[k] = z[k], z[i] }
+func (z sortPriorityNodeSiblingsRFC7540) Less(i, k int) bool {
// Prefer the subtree that has sent fewer bytes relative to its weight.
// See sections 5.3.2 and 5.3.4.
- wi, bi := float64(z[i].weight+1), float64(z[i].subtreeBytes)
- wk, bk := float64(z[k].weight+1), float64(z[k].subtreeBytes)
+ wi, bi := float64(z[i].weight)+1, float64(z[i].subtreeBytes)
+ wk, bk := float64(z[k].weight)+1, float64(z[k].subtreeBytes)
if bi == 0 && bk == 0 {
return wi >= wk
}
@@ -225,13 +225,13 @@ func (z sortPriorityNodeSiblings) Less(i, k int) bool {
return bi/bk <= wi/wk
}
-type priorityWriteScheduler struct {
+type priorityWriteSchedulerRFC7540 struct {
// root is the root of the priority tree, where root.id = 0.
// The root queues control frames that are not associated with any stream.
- root priorityNode
+ root priorityNodeRFC7540
// nodes maps stream ids to priority tree nodes.
- nodes map[uint32]*priorityNode
+ nodes map[uint32]*priorityNodeRFC7540
// maxID is the maximum stream id in nodes.
maxID uint32
@@ -239,7 +239,7 @@ type priorityWriteScheduler struct {
// lists of nodes that have been closed or are idle, but are kept in
// the tree for improved prioritization. When the lengths exceed either
// maxClosedNodesInTree or maxIdleNodesInTree, old nodes are discarded.
- closedNodes, idleNodes []*priorityNode
+ closedNodes, idleNodes []*priorityNodeRFC7540
// From the config.
maxClosedNodesInTree int
@@ -248,19 +248,19 @@ type priorityWriteScheduler struct {
enableWriteThrottle bool
// tmp is scratch space for priorityNode.walkReadyInOrder to reduce allocations.
- tmp []*priorityNode
+ tmp []*priorityNodeRFC7540
// pool of empty queues for reuse.
queuePool writeQueuePool
}
-func (ws *priorityWriteScheduler) OpenStream(streamID uint32, options OpenStreamOptions) {
+func (ws *priorityWriteSchedulerRFC7540) OpenStream(streamID uint32, options OpenStreamOptions) {
// The stream may be currently idle but cannot be opened or closed.
if curr := ws.nodes[streamID]; curr != nil {
- if curr.state != priorityNodeIdle {
+ if curr.state != priorityNodeIdleRFC7540 {
panic(fmt.Sprintf("stream %d already opened", streamID))
}
- curr.state = priorityNodeOpen
+ curr.state = priorityNodeOpenRFC7540
return
}
@@ -272,11 +272,11 @@ func (ws *priorityWriteScheduler) OpenStream(streamID uint32, options OpenStream
if parent == nil {
parent = &ws.root
}
- n := &priorityNode{
+ n := &priorityNodeRFC7540{
q: *ws.queuePool.get(),
id: streamID,
- weight: priorityDefaultWeight,
- state: priorityNodeOpen,
+ weight: priorityDefaultWeightRFC7540,
+ state: priorityNodeOpenRFC7540,
}
n.setParent(parent)
ws.nodes[streamID] = n
@@ -285,24 +285,23 @@ func (ws *priorityWriteScheduler) OpenStream(streamID uint32, options OpenStream
}
}
-func (ws *priorityWriteScheduler) CloseStream(streamID uint32) {
+func (ws *priorityWriteSchedulerRFC7540) CloseStream(streamID uint32) {
if streamID == 0 {
panic("violation of WriteScheduler interface: cannot close stream 0")
}
if ws.nodes[streamID] == nil {
panic(fmt.Sprintf("violation of WriteScheduler interface: unknown stream %d", streamID))
}
- if ws.nodes[streamID].state != priorityNodeOpen {
+ if ws.nodes[streamID].state != priorityNodeOpenRFC7540 {
panic(fmt.Sprintf("violation of WriteScheduler interface: stream %d already closed", streamID))
}
n := ws.nodes[streamID]
- n.state = priorityNodeClosed
+ n.state = priorityNodeClosedRFC7540
n.addBytes(-n.bytes)
q := n.q
ws.queuePool.put(&q)
- n.q.s = nil
if ws.maxClosedNodesInTree > 0 {
ws.addClosedOrIdleNode(&ws.closedNodes, ws.maxClosedNodesInTree, n)
} else {
@@ -310,7 +309,7 @@ func (ws *priorityWriteScheduler) CloseStream(streamID uint32) {
}
}
-func (ws *priorityWriteScheduler) AdjustStream(streamID uint32, priority PriorityParam) {
+func (ws *priorityWriteSchedulerRFC7540) AdjustStream(streamID uint32, priority PriorityParam) {
if streamID == 0 {
panic("adjustPriority on root")
}
@@ -324,11 +323,11 @@ func (ws *priorityWriteScheduler) AdjustStream(streamID uint32, priority Priorit
return
}
ws.maxID = streamID
- n = &priorityNode{
+ n = &priorityNodeRFC7540{
q: *ws.queuePool.get(),
id: streamID,
- weight: priorityDefaultWeight,
- state: priorityNodeIdle,
+ weight: priorityDefaultWeightRFC7540,
+ state: priorityNodeIdleRFC7540,
}
n.setParent(&ws.root)
ws.nodes[streamID] = n
@@ -340,7 +339,7 @@ func (ws *priorityWriteScheduler) AdjustStream(streamID uint32, priority Priorit
parent := ws.nodes[priority.StreamDep]
if parent == nil {
n.setParent(&ws.root)
- n.weight = priorityDefaultWeight
+ n.weight = priorityDefaultWeightRFC7540
return
}
@@ -381,8 +380,8 @@ func (ws *priorityWriteScheduler) AdjustStream(streamID uint32, priority Priorit
n.weight = priority.Weight
}
-func (ws *priorityWriteScheduler) Push(wr FrameWriteRequest) {
- var n *priorityNode
+func (ws *priorityWriteSchedulerRFC7540) Push(wr FrameWriteRequest) {
+ var n *priorityNodeRFC7540
if wr.isControl() {
n = &ws.root
} else {
@@ -401,8 +400,8 @@ func (ws *priorityWriteScheduler) Push(wr FrameWriteRequest) {
n.q.push(wr)
}
-func (ws *priorityWriteScheduler) Pop() (wr FrameWriteRequest, ok bool) {
- ws.root.walkReadyInOrder(false, &ws.tmp, func(n *priorityNode, openParent bool) bool {
+func (ws *priorityWriteSchedulerRFC7540) Pop() (wr FrameWriteRequest, ok bool) {
+ ws.root.walkReadyInOrder(false, &ws.tmp, func(n *priorityNodeRFC7540, openParent bool) bool {
limit := int32(math.MaxInt32)
if openParent {
limit = ws.writeThrottleLimit
@@ -428,7 +427,7 @@ func (ws *priorityWriteScheduler) Pop() (wr FrameWriteRequest, ok bool) {
return wr, ok
}
-func (ws *priorityWriteScheduler) addClosedOrIdleNode(list *[]*priorityNode, maxSize int, n *priorityNode) {
+func (ws *priorityWriteSchedulerRFC7540) addClosedOrIdleNode(list *[]*priorityNodeRFC7540, maxSize int, n *priorityNodeRFC7540) {
if maxSize == 0 {
return
}
@@ -442,7 +441,7 @@ func (ws *priorityWriteScheduler) addClosedOrIdleNode(list *[]*priorityNode, max
*list = append(*list, n)
}
-func (ws *priorityWriteScheduler) removeNode(n *priorityNode) {
+func (ws *priorityWriteSchedulerRFC7540) removeNode(n *priorityNodeRFC7540) {
for n.kids != nil {
n.kids.setParent(n.parent)
}
diff --git a/etcd/vendor/golang.org/x/net/http2/writesched_priority_rfc9218.go b/etcd/vendor/golang.org/x/net/http2/writesched_priority_rfc9218.go
new file mode 100644
index 0000000000..cb4cadc32d
--- /dev/null
+++ b/etcd/vendor/golang.org/x/net/http2/writesched_priority_rfc9218.go
@@ -0,0 +1,209 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http2
+
+import (
+ "fmt"
+ "math"
+)
+
+type streamMetadata struct {
+ location *writeQueue
+ priority PriorityParam
+}
+
+type priorityWriteSchedulerRFC9218 struct {
+ // control contains control frames (SETTINGS, PING, etc.).
+ control writeQueue
+
+ // heads contain the head of a circular list of streams.
+ // We put these heads within a nested array that represents urgency and
+ // incremental, as defined in
+ // https://www.rfc-editor.org/rfc/rfc9218.html#name-priority-parameters.
+ // 8 represents u=0 up to u=7, and 2 represents i=false and i=true.
+ heads [8][2]*writeQueue
+
+ // streams contains a mapping between each stream ID and their metadata, so
+ // we can quickly locate them when needing to, for example, adjust their
+ // priority.
+ streams map[uint32]streamMetadata
+
+ // queuePool are empty queues for reuse.
+ queuePool writeQueuePool
+
+ // prioritizeIncremental is used to determine whether we should prioritize
+ // incremental streams or not, when urgency is the same in a given Pop()
+ // call.
+ prioritizeIncremental bool
+}
+
+func newPriorityWriteSchedulerRFC9218() WriteScheduler {
+ ws := &priorityWriteSchedulerRFC9218{
+ streams: make(map[uint32]streamMetadata),
+ }
+ return ws
+}
+
+func (ws *priorityWriteSchedulerRFC9218) OpenStream(streamID uint32, opt OpenStreamOptions) {
+ if ws.streams[streamID].location != nil {
+ panic(fmt.Errorf("stream %d already opened", streamID))
+ }
+ q := ws.queuePool.get()
+ ws.streams[streamID] = streamMetadata{
+ location: q,
+ priority: opt.priority,
+ }
+
+ u, i := opt.priority.urgency, opt.priority.incremental
+ if ws.heads[u][i] == nil {
+ ws.heads[u][i] = q
+ q.next = q
+ q.prev = q
+ } else {
+ // Queues are stored in a ring.
+ // Insert the new stream before ws.head, putting it at the end of the list.
+ q.prev = ws.heads[u][i].prev
+ q.next = ws.heads[u][i]
+ q.prev.next = q
+ q.next.prev = q
+ }
+}
+
+func (ws *priorityWriteSchedulerRFC9218) CloseStream(streamID uint32) {
+ metadata := ws.streams[streamID]
+ q, u, i := metadata.location, metadata.priority.urgency, metadata.priority.incremental
+ if q == nil {
+ return
+ }
+ if q.next == q {
+ // This was the only open stream.
+ ws.heads[u][i] = nil
+ } else {
+ q.prev.next = q.next
+ q.next.prev = q.prev
+ if ws.heads[u][i] == q {
+ ws.heads[u][i] = q.next
+ }
+ }
+ delete(ws.streams, streamID)
+ ws.queuePool.put(q)
+}
+
+func (ws *priorityWriteSchedulerRFC9218) AdjustStream(streamID uint32, priority PriorityParam) {
+ metadata := ws.streams[streamID]
+ q, u, i := metadata.location, metadata.priority.urgency, metadata.priority.incremental
+ if q == nil {
+ return
+ }
+
+ // Remove stream from current location.
+ if q.next == q {
+ // This was the only open stream.
+ ws.heads[u][i] = nil
+ } else {
+ q.prev.next = q.next
+ q.next.prev = q.prev
+ if ws.heads[u][i] == q {
+ ws.heads[u][i] = q.next
+ }
+ }
+
+ // Insert stream to the new queue.
+ u, i = priority.urgency, priority.incremental
+ if ws.heads[u][i] == nil {
+ ws.heads[u][i] = q
+ q.next = q
+ q.prev = q
+ } else {
+ // Queues are stored in a ring.
+ // Insert the new stream before ws.head, putting it at the end of the list.
+ q.prev = ws.heads[u][i].prev
+ q.next = ws.heads[u][i]
+ q.prev.next = q
+ q.next.prev = q
+ }
+
+ // Update the metadata.
+ ws.streams[streamID] = streamMetadata{
+ location: q,
+ priority: priority,
+ }
+}
+
+func (ws *priorityWriteSchedulerRFC9218) Push(wr FrameWriteRequest) {
+ if wr.isControl() {
+ ws.control.push(wr)
+ return
+ }
+ q := ws.streams[wr.StreamID()].location
+ if q == nil {
+ // This is a closed stream.
+ // wr should not be a HEADERS or DATA frame.
+ // We push the request onto the control queue.
+ if wr.DataSize() > 0 {
+ panic("add DATA on non-open stream")
+ }
+ ws.control.push(wr)
+ return
+ }
+ q.push(wr)
+}
+
+func (ws *priorityWriteSchedulerRFC9218) Pop() (FrameWriteRequest, bool) {
+ // Control and RST_STREAM frames first.
+ if !ws.control.empty() {
+ return ws.control.shift(), true
+ }
+
+ // On the next Pop(), we want to prioritize incremental if we prioritized
+ // non-incremental request of the same urgency this time. Vice-versa.
+ // i.e. when there are incremental and non-incremental requests at the same
+ // priority, we give 50% of our bandwidth to the incremental ones in
+ // aggregate and 50% to the first non-incremental one (since
+ // non-incremental streams do not use round-robin writes).
+ ws.prioritizeIncremental = !ws.prioritizeIncremental
+
+ // Always prioritize lowest u (i.e. highest urgency level).
+ for u := range ws.heads {
+ for i := range ws.heads[u] {
+ // When we want to prioritize incremental, we try to pop i=true
+ // first before i=false when u is the same.
+ if ws.prioritizeIncremental {
+ i = (i + 1) % 2
+ }
+ q := ws.heads[u][i]
+ if q == nil {
+ continue
+ }
+ for {
+ if wr, ok := q.consume(math.MaxInt32); ok {
+ if i == 1 {
+ // For incremental streams, we update head to q.next so
+ // we can round-robin between multiple streams that can
+ // immediately benefit from partial writes.
+ ws.heads[u][i] = q.next
+ } else {
+ // For non-incremental streams, we try to finish one to
+ // completion rather than doing round-robin. However,
+ // we update head here so that if q.consume() is !ok
+ // (e.g. the stream has no more frame to consume), head
+ // is updated to the next q that has frames to consume
+ // on future iterations. This way, we do not prioritize
+ // writing to unavailable stream on next Pop() calls,
+ // preventing head-of-line blocking.
+ ws.heads[u][i] = q
+ }
+ return wr, true
+ }
+ q = q.next
+ if q == ws.heads[u][i] {
+ break
+ }
+ }
+
+ }
+ }
+ return FrameWriteRequest{}, false
+}
diff --git a/etcd/vendor/golang.org/x/net/http2/writesched_roundrobin.go b/etcd/vendor/golang.org/x/net/http2/writesched_roundrobin.go
index 54fe86322d..737cff9ecb 100644
--- a/etcd/vendor/golang.org/x/net/http2/writesched_roundrobin.go
+++ b/etcd/vendor/golang.org/x/net/http2/writesched_roundrobin.go
@@ -25,7 +25,7 @@ type roundRobinWriteScheduler struct {
}
// newRoundRobinWriteScheduler constructs a new write scheduler.
-// The round robin scheduler priorizes control frames
+// The round robin scheduler prioritizes control frames
// like SETTINGS and PING over DATA frames.
// When there are no control frames to send, it performs a round-robin
// selection from the ready streams.
diff --git a/etcd/vendor/golang.org/x/net/internal/httpcommon/request.go b/etcd/vendor/golang.org/x/net/internal/httpcommon/request.go
index 4b70553179..1e10f89ebf 100644
--- a/etcd/vendor/golang.org/x/net/internal/httpcommon/request.go
+++ b/etcd/vendor/golang.org/x/net/internal/httpcommon/request.go
@@ -51,7 +51,7 @@ type EncodeHeadersParam struct {
DefaultUserAgent string
}
-// EncodeHeadersParam is the result of EncodeHeaders.
+// EncodeHeadersResult is the result of EncodeHeaders.
type EncodeHeadersResult struct {
HasBody bool
HasTrailers bool
@@ -399,7 +399,7 @@ type ServerRequestResult struct {
// If the request should be rejected, this is a short string suitable for passing
// to the http2 package's CountError function.
- // It might be a bit odd to return errors this way rather than returing an error,
+ // It might be a bit odd to return errors this way rather than returning an error,
// but this ensures we don't forget to include a CountError reason.
InvalidReason string
}
diff --git a/etcd/vendor/golang.org/x/net/internal/socks/socks.go b/etcd/vendor/golang.org/x/net/internal/socks/socks.go
index 84fcc32b63..8eedb84cec 100644
--- a/etcd/vendor/golang.org/x/net/internal/socks/socks.go
+++ b/etcd/vendor/golang.org/x/net/internal/socks/socks.go
@@ -297,7 +297,7 @@ func (up *UsernamePassword) Authenticate(ctx context.Context, rw io.ReadWriter,
b = append(b, up.Username...)
b = append(b, byte(len(up.Password)))
b = append(b, up.Password...)
- // TODO(mikio): handle IO deadlines and cancelation if
+ // TODO(mikio): handle IO deadlines and cancellation if
// necessary
if _, err := rw.Write(b); err != nil {
return err
diff --git a/etcd/vendor/golang.org/x/sync/errgroup/errgroup.go b/etcd/vendor/golang.org/x/sync/errgroup/errgroup.go
index 1d8cffae8c..2f45dbc86e 100644
--- a/etcd/vendor/golang.org/x/sync/errgroup/errgroup.go
+++ b/etcd/vendor/golang.org/x/sync/errgroup/errgroup.go
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// Package errgroup provides synchronization, error propagation, and Context
-// cancelation for groups of goroutines working on subtasks of a common task.
+// cancellation for groups of goroutines working on subtasks of a common task.
//
// [errgroup.Group] is related to [sync.WaitGroup] but adds handling of tasks
// returning errors.
diff --git a/etcd/vendor/golang.org/x/sys/unix/affinity_linux.go b/etcd/vendor/golang.org/x/sys/unix/affinity_linux.go
index 3c7a6d6e2f..3ea470387b 100644
--- a/etcd/vendor/golang.org/x/sys/unix/affinity_linux.go
+++ b/etcd/vendor/golang.org/x/sys/unix/affinity_linux.go
@@ -41,6 +41,15 @@ func (s *CPUSet) Zero() {
clear(s[:])
}
+// Fill adds all possible CPU bits to the set s. On Linux, [SchedSetaffinity]
+// will silently ignore any invalid CPU bits in [CPUSet] so this is an
+// efficient way of resetting the CPU affinity of a process.
+func (s *CPUSet) Fill() {
+ for i := range s {
+ s[i] = ^cpuMask(0)
+ }
+}
+
func cpuBitsIndex(cpu int) int {
return cpu / _NCPUBITS
}
diff --git a/etcd/vendor/golang.org/x/sys/unix/fdset.go b/etcd/vendor/golang.org/x/sys/unix/fdset.go
index 9e83d18cd0..62ed12645f 100644
--- a/etcd/vendor/golang.org/x/sys/unix/fdset.go
+++ b/etcd/vendor/golang.org/x/sys/unix/fdset.go
@@ -23,7 +23,5 @@ func (fds *FdSet) IsSet(fd int) bool {
// Zero clears the set fds.
func (fds *FdSet) Zero() {
- for i := range fds.Bits {
- fds.Bits[i] = 0
- }
+ clear(fds.Bits[:])
}
diff --git a/etcd/vendor/golang.org/x/sys/unix/ifreq_linux.go b/etcd/vendor/golang.org/x/sys/unix/ifreq_linux.go
index 848840ae4c..309f5a2b0c 100644
--- a/etcd/vendor/golang.org/x/sys/unix/ifreq_linux.go
+++ b/etcd/vendor/golang.org/x/sys/unix/ifreq_linux.go
@@ -111,9 +111,7 @@ func (ifr *Ifreq) SetUint32(v uint32) {
// clear zeroes the ifreq's union field to prevent trailing garbage data from
// being sent to the kernel if an ifreq is reused.
func (ifr *Ifreq) clear() {
- for i := range ifr.raw.Ifru {
- ifr.raw.Ifru[i] = 0
- }
+ clear(ifr.raw.Ifru[:])
}
// TODO(mdlayher): export as IfreqData? For now we can provide helpers such as
diff --git a/etcd/vendor/golang.org/x/sys/unix/mkall.sh b/etcd/vendor/golang.org/x/sys/unix/mkall.sh
index e6f31d374d..d0ed611912 100644
--- a/etcd/vendor/golang.org/x/sys/unix/mkall.sh
+++ b/etcd/vendor/golang.org/x/sys/unix/mkall.sh
@@ -49,6 +49,7 @@ esac
if [[ "$GOOS" = "linux" ]]; then
# Use the Docker-based build system
# Files generated through docker (use $cmd so you can Ctl-C the build or run)
+ set -e
$cmd docker build --tag generate:$GOOS $GOOS
$cmd docker run --interactive --tty --volume $(cd -- "$(dirname -- "$0")/.." && pwd):/build generate:$GOOS
exit
diff --git a/etcd/vendor/golang.org/x/sys/unix/mkerrors.sh b/etcd/vendor/golang.org/x/sys/unix/mkerrors.sh
index d1c8b2640e..42517077c4 100644
--- a/etcd/vendor/golang.org/x/sys/unix/mkerrors.sh
+++ b/etcd/vendor/golang.org/x/sys/unix/mkerrors.sh
@@ -226,6 +226,7 @@ struct ltchars {
#include
#include
#include
+#include
#include
#include
#include
@@ -529,6 +530,7 @@ ccflags="$@"
$2 ~ /^O[CNPFPL][A-Z]+[^_][A-Z]+$/ ||
$2 ~ /^(NL|CR|TAB|BS|VT|FF)DLY$/ ||
$2 ~ /^(NL|CR|TAB|BS|VT|FF)[0-9]$/ ||
+ $2 ~ /^(DT|EI|ELF|EV|NN|NT|PF|SHF|SHN|SHT|STB|STT|VER)_/ ||
$2 ~ /^O?XTABS$/ ||
$2 ~ /^TC[IO](ON|OFF)$/ ||
$2 ~ /^IN_/ ||
diff --git a/etcd/vendor/golang.org/x/sys/unix/syscall_linux.go b/etcd/vendor/golang.org/x/sys/unix/syscall_linux.go
index 4958a65708..06c0eea6fb 100644
--- a/etcd/vendor/golang.org/x/sys/unix/syscall_linux.go
+++ b/etcd/vendor/golang.org/x/sys/unix/syscall_linux.go
@@ -801,9 +801,7 @@ func (sa *SockaddrPPPoE) sockaddr() (unsafe.Pointer, _Socklen, error) {
// one. The kernel expects SID to be in network byte order.
binary.BigEndian.PutUint16(sa.raw[6:8], sa.SID)
copy(sa.raw[8:14], sa.Remote)
- for i := 14; i < 14+IFNAMSIZ; i++ {
- sa.raw[i] = 0
- }
+ clear(sa.raw[14 : 14+IFNAMSIZ])
copy(sa.raw[14:], sa.Dev)
return unsafe.Pointer(&sa.raw), SizeofSockaddrPPPoX, nil
}
@@ -2645,3 +2643,9 @@ func SchedGetAttr(pid int, flags uint) (*SchedAttr, error) {
//sys Cachestat(fd uint, crange *CachestatRange, cstat *Cachestat_t, flags uint) (err error)
//sys Mseal(b []byte, flags uint) (err error)
+
+//sys setMemPolicy(mode int, mask *CPUSet, size int) (err error) = SYS_SET_MEMPOLICY
+
+func SetMemPolicy(mode int, mask *CPUSet) error {
+ return setMemPolicy(mode, mask, _CPU_SETSIZE)
+}
diff --git a/etcd/vendor/golang.org/x/sys/unix/syscall_netbsd.go b/etcd/vendor/golang.org/x/sys/unix/syscall_netbsd.go
index 88162099af..34a4676973 100644
--- a/etcd/vendor/golang.org/x/sys/unix/syscall_netbsd.go
+++ b/etcd/vendor/golang.org/x/sys/unix/syscall_netbsd.go
@@ -248,6 +248,23 @@ func Statvfs(path string, buf *Statvfs_t) (err error) {
return Statvfs1(path, buf, ST_WAIT)
}
+func Getvfsstat(buf []Statvfs_t, flags int) (n int, err error) {
+ var (
+ _p0 unsafe.Pointer
+ bufsize uintptr
+ )
+ if len(buf) > 0 {
+ _p0 = unsafe.Pointer(&buf[0])
+ bufsize = unsafe.Sizeof(Statvfs_t{}) * uintptr(len(buf))
+ }
+ r0, _, e1 := Syscall(SYS_GETVFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
+ n = int(r0)
+ if e1 != 0 {
+ err = e1
+ }
+ return
+}
+
/*
* Exposed directly
*/
diff --git a/etcd/vendor/golang.org/x/sys/unix/zerrors_linux.go b/etcd/vendor/golang.org/x/sys/unix/zerrors_linux.go
index b6db27d937..d0a75da572 100644
--- a/etcd/vendor/golang.org/x/sys/unix/zerrors_linux.go
+++ b/etcd/vendor/golang.org/x/sys/unix/zerrors_linux.go
@@ -853,20 +853,86 @@ const (
DM_VERSION_MAJOR = 0x4
DM_VERSION_MINOR = 0x32
DM_VERSION_PATCHLEVEL = 0x0
+ DT_ADDRRNGHI = 0x6ffffeff
+ DT_ADDRRNGLO = 0x6ffffe00
DT_BLK = 0x6
DT_CHR = 0x2
+ DT_DEBUG = 0x15
DT_DIR = 0x4
+ DT_ENCODING = 0x20
DT_FIFO = 0x1
+ DT_FINI = 0xd
+ DT_FLAGS_1 = 0x6ffffffb
+ DT_GNU_HASH = 0x6ffffef5
+ DT_HASH = 0x4
+ DT_HIOS = 0x6ffff000
+ DT_HIPROC = 0x7fffffff
+ DT_INIT = 0xc
+ DT_JMPREL = 0x17
DT_LNK = 0xa
+ DT_LOOS = 0x6000000d
+ DT_LOPROC = 0x70000000
+ DT_NEEDED = 0x1
+ DT_NULL = 0x0
+ DT_PLTGOT = 0x3
+ DT_PLTREL = 0x14
+ DT_PLTRELSZ = 0x2
DT_REG = 0x8
+ DT_REL = 0x11
+ DT_RELA = 0x7
+ DT_RELACOUNT = 0x6ffffff9
+ DT_RELAENT = 0x9
+ DT_RELASZ = 0x8
+ DT_RELCOUNT = 0x6ffffffa
+ DT_RELENT = 0x13
+ DT_RELSZ = 0x12
+ DT_RPATH = 0xf
DT_SOCK = 0xc
+ DT_SONAME = 0xe
+ DT_STRSZ = 0xa
+ DT_STRTAB = 0x5
+ DT_SYMBOLIC = 0x10
+ DT_SYMENT = 0xb
+ DT_SYMTAB = 0x6
+ DT_TEXTREL = 0x16
DT_UNKNOWN = 0x0
+ DT_VALRNGHI = 0x6ffffdff
+ DT_VALRNGLO = 0x6ffffd00
+ DT_VERDEF = 0x6ffffffc
+ DT_VERDEFNUM = 0x6ffffffd
+ DT_VERNEED = 0x6ffffffe
+ DT_VERNEEDNUM = 0x6fffffff
+ DT_VERSYM = 0x6ffffff0
DT_WHT = 0xe
ECHO = 0x8
ECRYPTFS_SUPER_MAGIC = 0xf15f
EFD_SEMAPHORE = 0x1
EFIVARFS_MAGIC = 0xde5e81e4
EFS_SUPER_MAGIC = 0x414a53
+ EI_CLASS = 0x4
+ EI_DATA = 0x5
+ EI_MAG0 = 0x0
+ EI_MAG1 = 0x1
+ EI_MAG2 = 0x2
+ EI_MAG3 = 0x3
+ EI_NIDENT = 0x10
+ EI_OSABI = 0x7
+ EI_PAD = 0x8
+ EI_VERSION = 0x6
+ ELFCLASS32 = 0x1
+ ELFCLASS64 = 0x2
+ ELFCLASSNONE = 0x0
+ ELFCLASSNUM = 0x3
+ ELFDATA2LSB = 0x1
+ ELFDATA2MSB = 0x2
+ ELFDATANONE = 0x0
+ ELFMAG = "\177ELF"
+ ELFMAG0 = 0x7f
+ ELFMAG1 = 'E'
+ ELFMAG2 = 'L'
+ ELFMAG3 = 'F'
+ ELFOSABI_LINUX = 0x3
+ ELFOSABI_NONE = 0x0
EM_386 = 0x3
EM_486 = 0x6
EM_68K = 0x4
@@ -1152,14 +1218,24 @@ const (
ETH_P_WCCP = 0x883e
ETH_P_X25 = 0x805
ETH_P_XDSA = 0xf8
+ ET_CORE = 0x4
+ ET_DYN = 0x3
+ ET_EXEC = 0x2
+ ET_HIPROC = 0xffff
+ ET_LOPROC = 0xff00
+ ET_NONE = 0x0
+ ET_REL = 0x1
EV_ABS = 0x3
EV_CNT = 0x20
+ EV_CURRENT = 0x1
EV_FF = 0x15
EV_FF_STATUS = 0x17
EV_KEY = 0x1
EV_LED = 0x11
EV_MAX = 0x1f
EV_MSC = 0x4
+ EV_NONE = 0x0
+ EV_NUM = 0x2
EV_PWR = 0x16
EV_REL = 0x2
EV_REP = 0x14
@@ -2276,7 +2352,167 @@ const (
NLM_F_REPLACE = 0x100
NLM_F_REQUEST = 0x1
NLM_F_ROOT = 0x100
+ NN_386_IOPERM = "LINUX"
+ NN_386_TLS = "LINUX"
+ NN_ARC_V2 = "LINUX"
+ NN_ARM_FPMR = "LINUX"
+ NN_ARM_GCS = "LINUX"
+ NN_ARM_HW_BREAK = "LINUX"
+ NN_ARM_HW_WATCH = "LINUX"
+ NN_ARM_PACA_KEYS = "LINUX"
+ NN_ARM_PACG_KEYS = "LINUX"
+ NN_ARM_PAC_ENABLED_KEYS = "LINUX"
+ NN_ARM_PAC_MASK = "LINUX"
+ NN_ARM_POE = "LINUX"
+ NN_ARM_SSVE = "LINUX"
+ NN_ARM_SVE = "LINUX"
+ NN_ARM_SYSTEM_CALL = "LINUX"
+ NN_ARM_TAGGED_ADDR_CTRL = "LINUX"
+ NN_ARM_TLS = "LINUX"
+ NN_ARM_VFP = "LINUX"
+ NN_ARM_ZA = "LINUX"
+ NN_ARM_ZT = "LINUX"
+ NN_AUXV = "CORE"
+ NN_FILE = "CORE"
+ NN_GNU_PROPERTY_TYPE_0 = "GNU"
+ NN_LOONGARCH_CPUCFG = "LINUX"
+ NN_LOONGARCH_CSR = "LINUX"
+ NN_LOONGARCH_HW_BREAK = "LINUX"
+ NN_LOONGARCH_HW_WATCH = "LINUX"
+ NN_LOONGARCH_LASX = "LINUX"
+ NN_LOONGARCH_LBT = "LINUX"
+ NN_LOONGARCH_LSX = "LINUX"
+ NN_MIPS_DSP = "LINUX"
+ NN_MIPS_FP_MODE = "LINUX"
+ NN_MIPS_MSA = "LINUX"
+ NN_PPC_DEXCR = "LINUX"
+ NN_PPC_DSCR = "LINUX"
+ NN_PPC_EBB = "LINUX"
+ NN_PPC_HASHKEYR = "LINUX"
+ NN_PPC_PKEY = "LINUX"
+ NN_PPC_PMU = "LINUX"
+ NN_PPC_PPR = "LINUX"
+ NN_PPC_SPE = "LINUX"
+ NN_PPC_TAR = "LINUX"
+ NN_PPC_TM_CDSCR = "LINUX"
+ NN_PPC_TM_CFPR = "LINUX"
+ NN_PPC_TM_CGPR = "LINUX"
+ NN_PPC_TM_CPPR = "LINUX"
+ NN_PPC_TM_CTAR = "LINUX"
+ NN_PPC_TM_CVMX = "LINUX"
+ NN_PPC_TM_CVSX = "LINUX"
+ NN_PPC_TM_SPR = "LINUX"
+ NN_PPC_VMX = "LINUX"
+ NN_PPC_VSX = "LINUX"
+ NN_PRFPREG = "CORE"
+ NN_PRPSINFO = "CORE"
+ NN_PRSTATUS = "CORE"
+ NN_PRXFPREG = "LINUX"
+ NN_RISCV_CSR = "LINUX"
+ NN_RISCV_TAGGED_ADDR_CTRL = "LINUX"
+ NN_RISCV_VECTOR = "LINUX"
+ NN_S390_CTRS = "LINUX"
+ NN_S390_GS_BC = "LINUX"
+ NN_S390_GS_CB = "LINUX"
+ NN_S390_HIGH_GPRS = "LINUX"
+ NN_S390_LAST_BREAK = "LINUX"
+ NN_S390_PREFIX = "LINUX"
+ NN_S390_PV_CPU_DATA = "LINUX"
+ NN_S390_RI_CB = "LINUX"
+ NN_S390_SYSTEM_CALL = "LINUX"
+ NN_S390_TDB = "LINUX"
+ NN_S390_TIMER = "LINUX"
+ NN_S390_TODCMP = "LINUX"
+ NN_S390_TODPREG = "LINUX"
+ NN_S390_VXRS_HIGH = "LINUX"
+ NN_S390_VXRS_LOW = "LINUX"
+ NN_SIGINFO = "CORE"
+ NN_TASKSTRUCT = "CORE"
+ NN_VMCOREDD = "LINUX"
+ NN_X86_SHSTK = "LINUX"
+ NN_X86_XSAVE_LAYOUT = "LINUX"
+ NN_X86_XSTATE = "LINUX"
NSFS_MAGIC = 0x6e736673
+ NT_386_IOPERM = 0x201
+ NT_386_TLS = 0x200
+ NT_ARC_V2 = 0x600
+ NT_ARM_FPMR = 0x40e
+ NT_ARM_GCS = 0x410
+ NT_ARM_HW_BREAK = 0x402
+ NT_ARM_HW_WATCH = 0x403
+ NT_ARM_PACA_KEYS = 0x407
+ NT_ARM_PACG_KEYS = 0x408
+ NT_ARM_PAC_ENABLED_KEYS = 0x40a
+ NT_ARM_PAC_MASK = 0x406
+ NT_ARM_POE = 0x40f
+ NT_ARM_SSVE = 0x40b
+ NT_ARM_SVE = 0x405
+ NT_ARM_SYSTEM_CALL = 0x404
+ NT_ARM_TAGGED_ADDR_CTRL = 0x409
+ NT_ARM_TLS = 0x401
+ NT_ARM_VFP = 0x400
+ NT_ARM_ZA = 0x40c
+ NT_ARM_ZT = 0x40d
+ NT_AUXV = 0x6
+ NT_FILE = 0x46494c45
+ NT_GNU_PROPERTY_TYPE_0 = 0x5
+ NT_LOONGARCH_CPUCFG = 0xa00
+ NT_LOONGARCH_CSR = 0xa01
+ NT_LOONGARCH_HW_BREAK = 0xa05
+ NT_LOONGARCH_HW_WATCH = 0xa06
+ NT_LOONGARCH_LASX = 0xa03
+ NT_LOONGARCH_LBT = 0xa04
+ NT_LOONGARCH_LSX = 0xa02
+ NT_MIPS_DSP = 0x800
+ NT_MIPS_FP_MODE = 0x801
+ NT_MIPS_MSA = 0x802
+ NT_PPC_DEXCR = 0x111
+ NT_PPC_DSCR = 0x105
+ NT_PPC_EBB = 0x106
+ NT_PPC_HASHKEYR = 0x112
+ NT_PPC_PKEY = 0x110
+ NT_PPC_PMU = 0x107
+ NT_PPC_PPR = 0x104
+ NT_PPC_SPE = 0x101
+ NT_PPC_TAR = 0x103
+ NT_PPC_TM_CDSCR = 0x10f
+ NT_PPC_TM_CFPR = 0x109
+ NT_PPC_TM_CGPR = 0x108
+ NT_PPC_TM_CPPR = 0x10e
+ NT_PPC_TM_CTAR = 0x10d
+ NT_PPC_TM_CVMX = 0x10a
+ NT_PPC_TM_CVSX = 0x10b
+ NT_PPC_TM_SPR = 0x10c
+ NT_PPC_VMX = 0x100
+ NT_PPC_VSX = 0x102
+ NT_PRFPREG = 0x2
+ NT_PRPSINFO = 0x3
+ NT_PRSTATUS = 0x1
+ NT_PRXFPREG = 0x46e62b7f
+ NT_RISCV_CSR = 0x900
+ NT_RISCV_TAGGED_ADDR_CTRL = 0x902
+ NT_RISCV_VECTOR = 0x901
+ NT_S390_CTRS = 0x304
+ NT_S390_GS_BC = 0x30c
+ NT_S390_GS_CB = 0x30b
+ NT_S390_HIGH_GPRS = 0x300
+ NT_S390_LAST_BREAK = 0x306
+ NT_S390_PREFIX = 0x305
+ NT_S390_PV_CPU_DATA = 0x30e
+ NT_S390_RI_CB = 0x30d
+ NT_S390_SYSTEM_CALL = 0x307
+ NT_S390_TDB = 0x308
+ NT_S390_TIMER = 0x301
+ NT_S390_TODCMP = 0x302
+ NT_S390_TODPREG = 0x303
+ NT_S390_VXRS_HIGH = 0x30a
+ NT_S390_VXRS_LOW = 0x309
+ NT_SIGINFO = 0x53494749
+ NT_TASKSTRUCT = 0x4
+ NT_VMCOREDD = 0x700
+ NT_X86_SHSTK = 0x204
+ NT_X86_XSAVE_LAYOUT = 0x205
+ NT_X86_XSTATE = 0x202
OCFS2_SUPER_MAGIC = 0x7461636f
OCRNL = 0x8
OFDEL = 0x80
@@ -2463,6 +2699,59 @@ const (
PERF_RECORD_MISC_USER = 0x2
PERF_SAMPLE_BRANCH_PLM_ALL = 0x7
PERF_SAMPLE_WEIGHT_TYPE = 0x1004000
+ PF_ALG = 0x26
+ PF_APPLETALK = 0x5
+ PF_ASH = 0x12
+ PF_ATMPVC = 0x8
+ PF_ATMSVC = 0x14
+ PF_AX25 = 0x3
+ PF_BLUETOOTH = 0x1f
+ PF_BRIDGE = 0x7
+ PF_CAIF = 0x25
+ PF_CAN = 0x1d
+ PF_DECnet = 0xc
+ PF_ECONET = 0x13
+ PF_FILE = 0x1
+ PF_IB = 0x1b
+ PF_IEEE802154 = 0x24
+ PF_INET = 0x2
+ PF_INET6 = 0xa
+ PF_IPX = 0x4
+ PF_IRDA = 0x17
+ PF_ISDN = 0x22
+ PF_IUCV = 0x20
+ PF_KCM = 0x29
+ PF_KEY = 0xf
+ PF_LLC = 0x1a
+ PF_LOCAL = 0x1
+ PF_MAX = 0x2e
+ PF_MCTP = 0x2d
+ PF_MPLS = 0x1c
+ PF_NETBEUI = 0xd
+ PF_NETLINK = 0x10
+ PF_NETROM = 0x6
+ PF_NFC = 0x27
+ PF_PACKET = 0x11
+ PF_PHONET = 0x23
+ PF_PPPOX = 0x18
+ PF_QIPCRTR = 0x2a
+ PF_R = 0x4
+ PF_RDS = 0x15
+ PF_ROSE = 0xb
+ PF_ROUTE = 0x10
+ PF_RXRPC = 0x21
+ PF_SECURITY = 0xe
+ PF_SMC = 0x2b
+ PF_SNA = 0x16
+ PF_TIPC = 0x1e
+ PF_UNIX = 0x1
+ PF_UNSPEC = 0x0
+ PF_VSOCK = 0x28
+ PF_W = 0x2
+ PF_WANPIPE = 0x19
+ PF_X = 0x1
+ PF_X25 = 0x9
+ PF_XDP = 0x2c
PID_FS_MAGIC = 0x50494446
PIPEFS_MAGIC = 0x50495045
PPPIOCGNPMODE = 0xc008744c
@@ -2758,6 +3047,23 @@ const (
PTRACE_SYSCALL_INFO_NONE = 0x0
PTRACE_SYSCALL_INFO_SECCOMP = 0x3
PTRACE_TRACEME = 0x0
+ PT_AARCH64_MEMTAG_MTE = 0x70000002
+ PT_DYNAMIC = 0x2
+ PT_GNU_EH_FRAME = 0x6474e550
+ PT_GNU_PROPERTY = 0x6474e553
+ PT_GNU_RELRO = 0x6474e552
+ PT_GNU_STACK = 0x6474e551
+ PT_HIOS = 0x6fffffff
+ PT_HIPROC = 0x7fffffff
+ PT_INTERP = 0x3
+ PT_LOAD = 0x1
+ PT_LOOS = 0x60000000
+ PT_LOPROC = 0x70000000
+ PT_NOTE = 0x4
+ PT_NULL = 0x0
+ PT_PHDR = 0x6
+ PT_SHLIB = 0x5
+ PT_TLS = 0x7
P_ALL = 0x0
P_PGID = 0x2
P_PID = 0x1
@@ -3091,6 +3397,47 @@ const (
SEEK_MAX = 0x4
SEEK_SET = 0x0
SELINUX_MAGIC = 0xf97cff8c
+ SHF_ALLOC = 0x2
+ SHF_EXCLUDE = 0x8000000
+ SHF_EXECINSTR = 0x4
+ SHF_GROUP = 0x200
+ SHF_INFO_LINK = 0x40
+ SHF_LINK_ORDER = 0x80
+ SHF_MASKOS = 0xff00000
+ SHF_MASKPROC = 0xf0000000
+ SHF_MERGE = 0x10
+ SHF_ORDERED = 0x4000000
+ SHF_OS_NONCONFORMING = 0x100
+ SHF_RELA_LIVEPATCH = 0x100000
+ SHF_RO_AFTER_INIT = 0x200000
+ SHF_STRINGS = 0x20
+ SHF_TLS = 0x400
+ SHF_WRITE = 0x1
+ SHN_ABS = 0xfff1
+ SHN_COMMON = 0xfff2
+ SHN_HIPROC = 0xff1f
+ SHN_HIRESERVE = 0xffff
+ SHN_LIVEPATCH = 0xff20
+ SHN_LOPROC = 0xff00
+ SHN_LORESERVE = 0xff00
+ SHN_UNDEF = 0x0
+ SHT_DYNAMIC = 0x6
+ SHT_DYNSYM = 0xb
+ SHT_HASH = 0x5
+ SHT_HIPROC = 0x7fffffff
+ SHT_HIUSER = 0xffffffff
+ SHT_LOPROC = 0x70000000
+ SHT_LOUSER = 0x80000000
+ SHT_NOBITS = 0x8
+ SHT_NOTE = 0x7
+ SHT_NULL = 0x0
+ SHT_NUM = 0xc
+ SHT_PROGBITS = 0x1
+ SHT_REL = 0x9
+ SHT_RELA = 0x4
+ SHT_SHLIB = 0xa
+ SHT_STRTAB = 0x3
+ SHT_SYMTAB = 0x2
SHUT_RD = 0x0
SHUT_RDWR = 0x2
SHUT_WR = 0x1
@@ -3317,6 +3664,16 @@ const (
STATX_UID = 0x8
STATX_WRITE_ATOMIC = 0x10000
STATX__RESERVED = 0x80000000
+ STB_GLOBAL = 0x1
+ STB_LOCAL = 0x0
+ STB_WEAK = 0x2
+ STT_COMMON = 0x5
+ STT_FILE = 0x4
+ STT_FUNC = 0x2
+ STT_NOTYPE = 0x0
+ STT_OBJECT = 0x1
+ STT_SECTION = 0x3
+ STT_TLS = 0x6
SYNC_FILE_RANGE_WAIT_AFTER = 0x4
SYNC_FILE_RANGE_WAIT_BEFORE = 0x1
SYNC_FILE_RANGE_WRITE = 0x2
@@ -3553,6 +3910,8 @@ const (
UTIME_OMIT = 0x3ffffffe
V9FS_MAGIC = 0x1021997
VERASE = 0x2
+ VER_FLG_BASE = 0x1
+ VER_FLG_WEAK = 0x2
VINTR = 0x0
VKILL = 0x3
VLNEXT = 0xf
diff --git a/etcd/vendor/golang.org/x/sys/unix/zsyscall_linux.go b/etcd/vendor/golang.org/x/sys/unix/zsyscall_linux.go
index 5cc1e8eb2f..8935d10a31 100644
--- a/etcd/vendor/golang.org/x/sys/unix/zsyscall_linux.go
+++ b/etcd/vendor/golang.org/x/sys/unix/zsyscall_linux.go
@@ -2238,3 +2238,13 @@ func Mseal(b []byte, flags uint) (err error) {
}
return
}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setMemPolicy(mode int, mask *CPUSet, size int) (err error) {
+ _, _, e1 := Syscall(SYS_SET_MEMPOLICY, uintptr(mode), uintptr(unsafe.Pointer(mask)), uintptr(size))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
diff --git a/etcd/vendor/golang.org/x/sys/unix/ztypes_linux.go b/etcd/vendor/golang.org/x/sys/unix/ztypes_linux.go
index 944e75a11c..c1a4670171 100644
--- a/etcd/vendor/golang.org/x/sys/unix/ztypes_linux.go
+++ b/etcd/vendor/golang.org/x/sys/unix/ztypes_linux.go
@@ -3590,6 +3590,8 @@ type Nhmsg struct {
Flags uint32
}
+const SizeofNhmsg = 0x8
+
type NexthopGrp struct {
Id uint32
Weight uint8
@@ -3597,6 +3599,8 @@ type NexthopGrp struct {
Resvd2 uint16
}
+const SizeofNexthopGrp = 0x8
+
const (
NHA_UNSPEC = 0x0
NHA_ID = 0x1
@@ -6332,3 +6336,30 @@ type SockDiagReq struct {
}
const RTM_NEWNVLAN = 0x70
+
+const (
+ MPOL_BIND = 0x2
+ MPOL_DEFAULT = 0x0
+ MPOL_F_ADDR = 0x2
+ MPOL_F_MEMS_ALLOWED = 0x4
+ MPOL_F_MOF = 0x8
+ MPOL_F_MORON = 0x10
+ MPOL_F_NODE = 0x1
+ MPOL_F_NUMA_BALANCING = 0x2000
+ MPOL_F_RELATIVE_NODES = 0x4000
+ MPOL_F_SHARED = 0x1
+ MPOL_F_STATIC_NODES = 0x8000
+ MPOL_INTERLEAVE = 0x3
+ MPOL_LOCAL = 0x4
+ MPOL_MAX = 0x7
+ MPOL_MF_INTERNAL = 0x10
+ MPOL_MF_LAZY = 0x8
+ MPOL_MF_MOVE_ALL = 0x4
+ MPOL_MF_MOVE = 0x2
+ MPOL_MF_STRICT = 0x1
+ MPOL_MF_VALID = 0x7
+ MPOL_MODE_FLAGS = 0xe000
+ MPOL_PREFERRED = 0x1
+ MPOL_PREFERRED_MANY = 0x5
+ MPOL_WEIGHTED_INTERLEAVE = 0x6
+)
diff --git a/etcd/vendor/golang.org/x/sys/windows/syscall_windows.go b/etcd/vendor/golang.org/x/sys/windows/syscall_windows.go
index 640f6b153f..69439df2a4 100644
--- a/etcd/vendor/golang.org/x/sys/windows/syscall_windows.go
+++ b/etcd/vendor/golang.org/x/sys/windows/syscall_windows.go
@@ -321,6 +321,8 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys SetConsoleOutputCP(cp uint32) (err error) = kernel32.SetConsoleOutputCP
//sys WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) = kernel32.WriteConsoleW
//sys ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) = kernel32.ReadConsoleW
+//sys GetNumberOfConsoleInputEvents(console Handle, numevents *uint32) (err error) = kernel32.GetNumberOfConsoleInputEvents
+//sys FlushConsoleInputBuffer(console Handle) (err error) = kernel32.FlushConsoleInputBuffer
//sys resizePseudoConsole(pconsole Handle, size uint32) (hr error) = kernel32.ResizePseudoConsole
//sys CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) [failretval==InvalidHandle] = kernel32.CreateToolhelp32Snapshot
//sys Module32First(snapshot Handle, moduleEntry *ModuleEntry32) (err error) = kernel32.Module32FirstW
@@ -890,8 +892,12 @@ const socket_error = uintptr(^uint32(0))
//sys MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar
//sys getBestInterfaceEx(sockaddr unsafe.Pointer, pdwBestIfIndex *uint32) (errcode error) = iphlpapi.GetBestInterfaceEx
//sys GetIfEntry2Ex(level uint32, row *MibIfRow2) (errcode error) = iphlpapi.GetIfEntry2Ex
+//sys GetIpForwardEntry2(row *MibIpForwardRow2) (errcode error) = iphlpapi.GetIpForwardEntry2
+//sys GetIpForwardTable2(family uint16, table **MibIpForwardTable2) (errcode error) = iphlpapi.GetIpForwardTable2
//sys GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) = iphlpapi.GetUnicastIpAddressEntry
+//sys FreeMibTable(memory unsafe.Pointer) = iphlpapi.FreeMibTable
//sys NotifyIpInterfaceChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyIpInterfaceChange
+//sys NotifyRouteChange2(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyRouteChange2
//sys NotifyUnicastIpAddressChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyUnicastIpAddressChange
//sys CancelMibChangeNotify2(notificationHandle Handle) (errcode error) = iphlpapi.CancelMibChangeNotify2
@@ -914,6 +920,17 @@ type RawSockaddrInet6 struct {
Scope_id uint32
}
+// RawSockaddrInet is a union that contains an IPv4, an IPv6 address, or an address family. See
+// https://learn.microsoft.com/en-us/windows/win32/api/ws2ipdef/ns-ws2ipdef-sockaddr_inet.
+//
+// A [*RawSockaddrInet] may be converted to a [*RawSockaddrInet4] or [*RawSockaddrInet6] using
+// unsafe, depending on the address family.
+type RawSockaddrInet struct {
+ Family uint16
+ Port uint16
+ Data [6]uint32
+}
+
type RawSockaddr struct {
Family uint16
Data [14]int8
diff --git a/etcd/vendor/golang.org/x/sys/windows/types_windows.go b/etcd/vendor/golang.org/x/sys/windows/types_windows.go
index 993a2297db..6e4f50eb48 100644
--- a/etcd/vendor/golang.org/x/sys/windows/types_windows.go
+++ b/etcd/vendor/golang.org/x/sys/windows/types_windows.go
@@ -65,6 +65,22 @@ var signals = [...]string{
15: "terminated",
}
+// File flags for [os.OpenFile]. The O_ prefix is used to indicate
+// that these flags are specific to the OpenFile function.
+const (
+ O_FILE_FLAG_OPEN_NO_RECALL = FILE_FLAG_OPEN_NO_RECALL
+ O_FILE_FLAG_OPEN_REPARSE_POINT = FILE_FLAG_OPEN_REPARSE_POINT
+ O_FILE_FLAG_SESSION_AWARE = FILE_FLAG_SESSION_AWARE
+ O_FILE_FLAG_POSIX_SEMANTICS = FILE_FLAG_POSIX_SEMANTICS
+ O_FILE_FLAG_BACKUP_SEMANTICS = FILE_FLAG_BACKUP_SEMANTICS
+ O_FILE_FLAG_DELETE_ON_CLOSE = FILE_FLAG_DELETE_ON_CLOSE
+ O_FILE_FLAG_SEQUENTIAL_SCAN = FILE_FLAG_SEQUENTIAL_SCAN
+ O_FILE_FLAG_RANDOM_ACCESS = FILE_FLAG_RANDOM_ACCESS
+ O_FILE_FLAG_NO_BUFFERING = FILE_FLAG_NO_BUFFERING
+ O_FILE_FLAG_OVERLAPPED = FILE_FLAG_OVERLAPPED
+ O_FILE_FLAG_WRITE_THROUGH = FILE_FLAG_WRITE_THROUGH
+)
+
const (
FILE_READ_DATA = 0x00000001
FILE_READ_ATTRIBUTES = 0x00000080
@@ -2304,6 +2320,82 @@ type MibIfRow2 struct {
OutQLen uint64
}
+// IP_ADDRESS_PREFIX stores an IP address prefix. See
+// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-ip_address_prefix.
+type IpAddressPrefix struct {
+ Prefix RawSockaddrInet
+ PrefixLength uint8
+}
+
+// NL_ROUTE_ORIGIN enumeration from nldef.h or
+// https://learn.microsoft.com/en-us/windows/win32/api/nldef/ne-nldef-nl_route_origin.
+const (
+ NlroManual = 0
+ NlroWellKnown = 1
+ NlroDHCP = 2
+ NlroRouterAdvertisement = 3
+ Nlro6to4 = 4
+)
+
+// NL_ROUTE_ORIGIN enumeration from nldef.h or
+// https://learn.microsoft.com/en-us/windows/win32/api/nldef/ne-nldef-nl_route_protocol.
+const (
+ MIB_IPPROTO_OTHER = 1
+ MIB_IPPROTO_LOCAL = 2
+ MIB_IPPROTO_NETMGMT = 3
+ MIB_IPPROTO_ICMP = 4
+ MIB_IPPROTO_EGP = 5
+ MIB_IPPROTO_GGP = 6
+ MIB_IPPROTO_HELLO = 7
+ MIB_IPPROTO_RIP = 8
+ MIB_IPPROTO_IS_IS = 9
+ MIB_IPPROTO_ES_IS = 10
+ MIB_IPPROTO_CISCO = 11
+ MIB_IPPROTO_BBN = 12
+ MIB_IPPROTO_OSPF = 13
+ MIB_IPPROTO_BGP = 14
+ MIB_IPPROTO_IDPR = 15
+ MIB_IPPROTO_EIGRP = 16
+ MIB_IPPROTO_DVMRP = 17
+ MIB_IPPROTO_RPL = 18
+ MIB_IPPROTO_DHCP = 19
+ MIB_IPPROTO_NT_AUTOSTATIC = 10002
+ MIB_IPPROTO_NT_STATIC = 10006
+ MIB_IPPROTO_NT_STATIC_NON_DOD = 10007
+)
+
+// MIB_IPFORWARD_ROW2 stores information about an IP route entry. See
+// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_ipforward_row2.
+type MibIpForwardRow2 struct {
+ InterfaceLuid uint64
+ InterfaceIndex uint32
+ DestinationPrefix IpAddressPrefix
+ NextHop RawSockaddrInet
+ SitePrefixLength uint8
+ ValidLifetime uint32
+ PreferredLifetime uint32
+ Metric uint32
+ Protocol uint32
+ Loopback uint8
+ AutoconfigureAddress uint8
+ Publish uint8
+ Immortal uint8
+ Age uint32
+ Origin uint32
+}
+
+// MIB_IPFORWARD_TABLE2 contains a table of IP route entries. See
+// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_ipforward_table2.
+type MibIpForwardTable2 struct {
+ NumEntries uint32
+ Table [1]MibIpForwardRow2
+}
+
+// Rows returns the IP route entries in the table.
+func (t *MibIpForwardTable2) Rows() []MibIpForwardRow2 {
+ return unsafe.Slice(&t.Table[0], t.NumEntries)
+}
+
// MIB_UNICASTIPADDRESS_ROW stores information about a unicast IP address. See
// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_unicastipaddress_row.
type MibUnicastIpAddressRow struct {
diff --git a/etcd/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/etcd/vendor/golang.org/x/sys/windows/zsyscall_windows.go
index 641a5f4b77..f25b7308a1 100644
--- a/etcd/vendor/golang.org/x/sys/windows/zsyscall_windows.go
+++ b/etcd/vendor/golang.org/x/sys/windows/zsyscall_windows.go
@@ -182,13 +182,17 @@ var (
procDwmGetWindowAttribute = moddwmapi.NewProc("DwmGetWindowAttribute")
procDwmSetWindowAttribute = moddwmapi.NewProc("DwmSetWindowAttribute")
procCancelMibChangeNotify2 = modiphlpapi.NewProc("CancelMibChangeNotify2")
+ procFreeMibTable = modiphlpapi.NewProc("FreeMibTable")
procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses")
procGetAdaptersInfo = modiphlpapi.NewProc("GetAdaptersInfo")
procGetBestInterfaceEx = modiphlpapi.NewProc("GetBestInterfaceEx")
procGetIfEntry = modiphlpapi.NewProc("GetIfEntry")
procGetIfEntry2Ex = modiphlpapi.NewProc("GetIfEntry2Ex")
+ procGetIpForwardEntry2 = modiphlpapi.NewProc("GetIpForwardEntry2")
+ procGetIpForwardTable2 = modiphlpapi.NewProc("GetIpForwardTable2")
procGetUnicastIpAddressEntry = modiphlpapi.NewProc("GetUnicastIpAddressEntry")
procNotifyIpInterfaceChange = modiphlpapi.NewProc("NotifyIpInterfaceChange")
+ procNotifyRouteChange2 = modiphlpapi.NewProc("NotifyRouteChange2")
procNotifyUnicastIpAddressChange = modiphlpapi.NewProc("NotifyUnicastIpAddressChange")
procAddDllDirectory = modkernel32.NewProc("AddDllDirectory")
procAssignProcessToJobObject = modkernel32.NewProc("AssignProcessToJobObject")
@@ -238,6 +242,7 @@ var (
procFindResourceW = modkernel32.NewProc("FindResourceW")
procFindVolumeClose = modkernel32.NewProc("FindVolumeClose")
procFindVolumeMountPointClose = modkernel32.NewProc("FindVolumeMountPointClose")
+ procFlushConsoleInputBuffer = modkernel32.NewProc("FlushConsoleInputBuffer")
procFlushFileBuffers = modkernel32.NewProc("FlushFileBuffers")
procFlushViewOfFile = modkernel32.NewProc("FlushViewOfFile")
procFormatMessageW = modkernel32.NewProc("FormatMessageW")
@@ -284,6 +289,7 @@ var (
procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW")
procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo")
procGetNamedPipeServerProcessId = modkernel32.NewProc("GetNamedPipeServerProcessId")
+ procGetNumberOfConsoleInputEvents = modkernel32.NewProc("GetNumberOfConsoleInputEvents")
procGetOverlappedResult = modkernel32.NewProc("GetOverlappedResult")
procGetPriorityClass = modkernel32.NewProc("GetPriorityClass")
procGetProcAddress = modkernel32.NewProc("GetProcAddress")
@@ -1622,6 +1628,11 @@ func CancelMibChangeNotify2(notificationHandle Handle) (errcode error) {
return
}
+func FreeMibTable(memory unsafe.Pointer) {
+ syscall.SyscallN(procFreeMibTable.Addr(), uintptr(memory))
+ return
+}
+
func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) {
r0, _, _ := syscall.SyscallN(procGetAdaptersAddresses.Addr(), uintptr(family), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(adapterAddresses)), uintptr(unsafe.Pointer(sizePointer)))
if r0 != 0 {
@@ -1662,6 +1673,22 @@ func GetIfEntry2Ex(level uint32, row *MibIfRow2) (errcode error) {
return
}
+func GetIpForwardEntry2(row *MibIpForwardRow2) (errcode error) {
+ r0, _, _ := syscall.SyscallN(procGetIpForwardEntry2.Addr(), uintptr(unsafe.Pointer(row)))
+ if r0 != 0 {
+ errcode = syscall.Errno(r0)
+ }
+ return
+}
+
+func GetIpForwardTable2(family uint16, table **MibIpForwardTable2) (errcode error) {
+ r0, _, _ := syscall.SyscallN(procGetIpForwardTable2.Addr(), uintptr(family), uintptr(unsafe.Pointer(table)))
+ if r0 != 0 {
+ errcode = syscall.Errno(r0)
+ }
+ return
+}
+
func GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) {
r0, _, _ := syscall.SyscallN(procGetUnicastIpAddressEntry.Addr(), uintptr(unsafe.Pointer(row)))
if r0 != 0 {
@@ -1682,6 +1709,18 @@ func NotifyIpInterfaceChange(family uint16, callback uintptr, callerContext unsa
return
}
+func NotifyRouteChange2(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) {
+ var _p0 uint32
+ if initialNotification {
+ _p0 = 1
+ }
+ r0, _, _ := syscall.SyscallN(procNotifyRouteChange2.Addr(), uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle)))
+ if r0 != 0 {
+ errcode = syscall.Errno(r0)
+ }
+ return
+}
+
func NotifyUnicastIpAddressChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) {
var _p0 uint32
if initialNotification {
@@ -2111,6 +2150,14 @@ func FindVolumeMountPointClose(findVolumeMountPoint Handle) (err error) {
return
}
+func FlushConsoleInputBuffer(console Handle) (err error) {
+ r1, _, e1 := syscall.SyscallN(procFlushConsoleInputBuffer.Addr(), uintptr(console))
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
func FlushFileBuffers(handle Handle) (err error) {
r1, _, e1 := syscall.SyscallN(procFlushFileBuffers.Addr(), uintptr(handle))
if r1 == 0 {
@@ -2481,6 +2528,14 @@ func GetNamedPipeServerProcessId(pipe Handle, serverProcessID *uint32) (err erro
return
}
+func GetNumberOfConsoleInputEvents(console Handle, numevents *uint32) (err error) {
+ r1, _, e1 := syscall.SyscallN(procGetNumberOfConsoleInputEvents.Addr(), uintptr(console), uintptr(unsafe.Pointer(numevents)))
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
func GetOverlappedResult(handle Handle, overlapped *Overlapped, done *uint32, wait bool) (err error) {
var _p0 uint32
if wait {
diff --git a/etcd/vendor/golang.org/x/term/terminal.go b/etcd/vendor/golang.org/x/term/terminal.go
index bddb2e2aeb..9255449b9b 100644
--- a/etcd/vendor/golang.org/x/term/terminal.go
+++ b/etcd/vendor/golang.org/x/term/terminal.go
@@ -413,7 +413,7 @@ func (t *Terminal) eraseNPreviousChars(n int) {
}
}
-// countToLeftWord returns then number of characters from the cursor to the
+// countToLeftWord returns the number of characters from the cursor to the
// start of the previous word.
func (t *Terminal) countToLeftWord() int {
if t.pos == 0 {
@@ -438,7 +438,7 @@ func (t *Terminal) countToLeftWord() int {
return t.pos - pos
}
-// countToRightWord returns then number of characters from the cursor to the
+// countToRightWord returns the number of characters from the cursor to the
// start of the next word.
func (t *Terminal) countToRightWord() int {
pos := t.pos
@@ -478,7 +478,7 @@ func visualLength(runes []rune) int {
return length
}
-// histroryAt unlocks the terminal and relocks it while calling History.At.
+// historyAt unlocks the terminal and relocks it while calling History.At.
func (t *Terminal) historyAt(idx int) (string, bool) {
t.lock.Unlock() // Unlock to avoid deadlock if History methods use the output writer.
defer t.lock.Lock() // panic in At (or Len) protection.
diff --git a/etcd/vendor/golang.org/x/text/unicode/bidi/core.go b/etcd/vendor/golang.org/x/text/unicode/bidi/core.go
index 9d2ae547b5..fb8273236d 100644
--- a/etcd/vendor/golang.org/x/text/unicode/bidi/core.go
+++ b/etcd/vendor/golang.org/x/text/unicode/bidi/core.go
@@ -427,13 +427,6 @@ type isolatingRunSequence struct {
func (i *isolatingRunSequence) Len() int { return len(i.indexes) }
-func maxLevel(a, b level) level {
- if a > b {
- return a
- }
- return b
-}
-
// Rule X10, second bullet: Determine the start-of-sequence (sos) and end-of-sequence (eos) types,
// either L or R, for each isolating run sequence.
func (p *paragraph) isolatingRunSequence(indexes []int) *isolatingRunSequence {
@@ -474,8 +467,8 @@ func (p *paragraph) isolatingRunSequence(indexes []int) *isolatingRunSequence {
indexes: indexes,
types: types,
level: level,
- sos: typeForLevel(maxLevel(prevLevel, level)),
- eos: typeForLevel(maxLevel(succLevel, level)),
+ sos: typeForLevel(max(prevLevel, level)),
+ eos: typeForLevel(max(succLevel, level)),
}
}
diff --git a/etcd/vendor/gopkg.in/evanphx/json-patch.v4/README.md b/etcd/vendor/gopkg.in/evanphx/json-patch.v4/README.md
index 28e3516937..86fefd5bf7 100644
--- a/etcd/vendor/gopkg.in/evanphx/json-patch.v4/README.md
+++ b/etcd/vendor/gopkg.in/evanphx/json-patch.v4/README.md
@@ -4,7 +4,7 @@
well as for calculating & applying [RFC7396 JSON merge patches](https://tools.ietf.org/html/rfc7396).
[](http://godoc.org/github.com/evanphx/json-patch)
-[](https://travis-ci.org/evanphx/json-patch)
+[](https://github.com/evanphx/json-patch/actions/workflows/go.yml)
[](https://goreportcard.com/report/github.com/evanphx/json-patch)
# Get It!
@@ -14,9 +14,7 @@ well as for calculating & applying [RFC7396 JSON merge patches](https://tools.ie
go get -u github.com/evanphx/json-patch/v5
```
-**Stable Versions**:
-* Version 5: `go get -u gopkg.in/evanphx/json-patch.v5`
-* Version 4: `go get -u gopkg.in/evanphx/json-patch.v4`
+If you need version 4, use `go get -u gopkg.in/evanphx/json-patch.v4`
(previous versions below `v3` are unavailable)
@@ -314,4 +312,4 @@ go test -cover ./...
```
Builds for pull requests are tested automatically
-using [TravisCI](https://travis-ci.org/evanphx/json-patch).
+using [GitHub Actions](https://github.com/evanphx/json-patch/actions/workflows/go.yml).
diff --git a/etcd/vendor/gopkg.in/evanphx/json-patch.v4/patch.go b/etcd/vendor/gopkg.in/evanphx/json-patch.v4/patch.go
index dc2b7e51e6..95136681ba 100644
--- a/etcd/vendor/gopkg.in/evanphx/json-patch.v4/patch.go
+++ b/etcd/vendor/gopkg.in/evanphx/json-patch.v4/patch.go
@@ -3,11 +3,10 @@ package jsonpatch
import (
"bytes"
"encoding/json"
+ "errors"
"fmt"
"strconv"
"strings"
-
- "github.com/pkg/errors"
)
const (
@@ -277,7 +276,7 @@ func (o Operation) Path() (string, error) {
return op, nil
}
- return "unknown", errors.Wrapf(ErrMissing, "operation missing path field")
+ return "unknown", fmt.Errorf("operation missing path field: %w", ErrMissing)
}
// From reads the "from" field of the Operation.
@@ -294,7 +293,7 @@ func (o Operation) From() (string, error) {
return op, nil
}
- return "unknown", errors.Wrapf(ErrMissing, "operation, missing from field")
+ return "unknown", fmt.Errorf("operation, missing from field: %w", ErrMissing)
}
func (o Operation) value() *lazyNode {
@@ -319,7 +318,7 @@ func (o Operation) ValueInterface() (interface{}, error) {
return v, nil
}
- return nil, errors.Wrapf(ErrMissing, "operation, missing value field")
+ return nil, fmt.Errorf("operation, missing value field: %w", ErrMissing)
}
func isArray(buf []byte) bool {
@@ -359,7 +358,7 @@ func findObject(pd *container, path string) (container, string) {
next, ok := doc.get(decodePatchKey(part))
- if next == nil || ok != nil {
+ if next == nil || ok != nil || next.raw == nil {
return nil, ""
}
@@ -398,7 +397,7 @@ func (d *partialDoc) get(key string) (*lazyNode, error) {
func (d *partialDoc) remove(key string) error {
_, ok := (*d)[key]
if !ok {
- return errors.Wrapf(ErrMissing, "Unable to remove nonexistent key: %s", key)
+ return fmt.Errorf("Unable to remove nonexistent key: %s: %w", key, ErrMissing)
}
delete(*d, key)
@@ -415,10 +414,10 @@ func (d *partialArray) set(key string, val *lazyNode) error {
if idx < 0 {
if !SupportNegativeIndices {
- return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+ return fmt.Errorf("Unable to access invalid index: %d: %w", idx, ErrInvalidIndex)
}
if idx < -len(*d) {
- return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+ return fmt.Errorf("Unable to access invalid index: %d: %w", idx, ErrInvalidIndex)
}
idx += len(*d)
}
@@ -435,7 +434,7 @@ func (d *partialArray) add(key string, val *lazyNode) error {
idx, err := strconv.Atoi(key)
if err != nil {
- return errors.Wrapf(err, "value was not a proper array index: '%s'", key)
+ return fmt.Errorf("value was not a proper array index: '%s': %w", key, err)
}
sz := len(*d) + 1
@@ -445,15 +444,15 @@ func (d *partialArray) add(key string, val *lazyNode) error {
cur := *d
if idx >= len(ary) {
- return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+ return fmt.Errorf("Unable to access invalid index: %d: %w", idx, ErrInvalidIndex)
}
if idx < 0 {
if !SupportNegativeIndices {
- return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+ return fmt.Errorf("Unable to access invalid index: %d: %w", idx, ErrInvalidIndex)
}
if idx < -len(ary) {
- return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+ return fmt.Errorf("Unable to access invalid index: %d: %w", idx, ErrInvalidIndex)
}
idx += len(ary)
}
@@ -475,16 +474,16 @@ func (d *partialArray) get(key string) (*lazyNode, error) {
if idx < 0 {
if !SupportNegativeIndices {
- return nil, errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+ return nil, fmt.Errorf("Unable to access invalid index: %d: %w", idx, ErrInvalidIndex)
}
if idx < -len(*d) {
- return nil, errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+ return nil, fmt.Errorf("Unable to access invalid index: %d: %w", idx, ErrInvalidIndex)
}
idx += len(*d)
}
if idx >= len(*d) {
- return nil, errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+ return nil, fmt.Errorf("Unable to access invalid index: %d: %w", idx, ErrInvalidIndex)
}
return (*d)[idx], nil
@@ -499,15 +498,15 @@ func (d *partialArray) remove(key string) error {
cur := *d
if idx >= len(cur) {
- return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+ return fmt.Errorf("Unable to access invalid index: %d: %w", idx, ErrInvalidIndex)
}
if idx < 0 {
if !SupportNegativeIndices {
- return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+ return fmt.Errorf("Unable to access invalid index: %d: %w", idx, ErrInvalidIndex)
}
if idx < -len(cur) {
- return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+ return fmt.Errorf("Unable to access invalid index: %d: %w", idx, ErrInvalidIndex)
}
idx += len(cur)
}
@@ -525,18 +524,18 @@ func (d *partialArray) remove(key string) error {
func (p Patch) add(doc *container, op Operation) error {
path, err := op.Path()
if err != nil {
- return errors.Wrapf(ErrMissing, "add operation failed to decode path")
+ return fmt.Errorf("add operation failed to decode path: %w", ErrMissing)
}
con, key := findObject(doc, path)
if con == nil {
- return errors.Wrapf(ErrMissing, "add operation does not apply: doc is missing path: \"%s\"", path)
+ return fmt.Errorf("add operation does not apply: doc is missing path: \"%s\": %w", path, ErrMissing)
}
err = con.add(key, op.value())
if err != nil {
- return errors.Wrapf(err, "error in add for path: '%s'", path)
+ return fmt.Errorf("error in add for path: '%s': %w", path, err)
}
return nil
@@ -545,18 +544,18 @@ func (p Patch) add(doc *container, op Operation) error {
func (p Patch) remove(doc *container, op Operation) error {
path, err := op.Path()
if err != nil {
- return errors.Wrapf(ErrMissing, "remove operation failed to decode path")
+ return fmt.Errorf("remove operation failed to decode path: %w", ErrMissing)
}
con, key := findObject(doc, path)
if con == nil {
- return errors.Wrapf(ErrMissing, "remove operation does not apply: doc is missing path: \"%s\"", path)
+ return fmt.Errorf("remove operation does not apply: doc is missing path: \"%s\": %w", path, ErrMissing)
}
err = con.remove(key)
if err != nil {
- return errors.Wrapf(err, "error in remove for path: '%s'", path)
+ return fmt.Errorf("error in remove for path: '%s': %w", path, err)
}
return nil
@@ -565,7 +564,7 @@ func (p Patch) remove(doc *container, op Operation) error {
func (p Patch) replace(doc *container, op Operation) error {
path, err := op.Path()
if err != nil {
- return errors.Wrapf(err, "replace operation failed to decode path")
+ return fmt.Errorf("replace operation failed to decode path: %w", err)
}
if path == "" {
@@ -574,7 +573,7 @@ func (p Patch) replace(doc *container, op Operation) error {
if val.which == eRaw {
if !val.tryDoc() {
if !val.tryAry() {
- return errors.Wrapf(err, "replace operation value must be object or array")
+ return fmt.Errorf("replace operation value must be object or array: %w", err)
}
}
}
@@ -585,7 +584,7 @@ func (p Patch) replace(doc *container, op Operation) error {
case eDoc:
*doc = &val.doc
case eRaw:
- return errors.Wrapf(err, "replace operation hit impossible case")
+ return fmt.Errorf("replace operation hit impossible case: %w", err)
}
return nil
@@ -594,17 +593,17 @@ func (p Patch) replace(doc *container, op Operation) error {
con, key := findObject(doc, path)
if con == nil {
- return errors.Wrapf(ErrMissing, "replace operation does not apply: doc is missing path: %s", path)
+ return fmt.Errorf("replace operation does not apply: doc is missing path: %s: %w", path, ErrMissing)
}
_, ok := con.get(key)
if ok != nil {
- return errors.Wrapf(ErrMissing, "replace operation does not apply: doc is missing key: %s", path)
+ return fmt.Errorf("replace operation does not apply: doc is missing key: %s: %w", path, ErrMissing)
}
err = con.set(key, op.value())
if err != nil {
- return errors.Wrapf(err, "error in remove for path: '%s'", path)
+ return fmt.Errorf("error in remove for path: '%s': %w", path, err)
}
return nil
@@ -613,39 +612,39 @@ func (p Patch) replace(doc *container, op Operation) error {
func (p Patch) move(doc *container, op Operation) error {
from, err := op.From()
if err != nil {
- return errors.Wrapf(err, "move operation failed to decode from")
+ return fmt.Errorf("move operation failed to decode from: %w", err)
}
con, key := findObject(doc, from)
if con == nil {
- return errors.Wrapf(ErrMissing, "move operation does not apply: doc is missing from path: %s", from)
+ return fmt.Errorf("move operation does not apply: doc is missing from path: %s: %w", from, ErrMissing)
}
val, err := con.get(key)
if err != nil {
- return errors.Wrapf(err, "error in move for path: '%s'", key)
+ return fmt.Errorf("error in move for path: '%s': %w", key, err)
}
err = con.remove(key)
if err != nil {
- return errors.Wrapf(err, "error in move for path: '%s'", key)
+ return fmt.Errorf("error in move for path: '%s': %w", key, err)
}
path, err := op.Path()
if err != nil {
- return errors.Wrapf(err, "move operation failed to decode path")
+ return fmt.Errorf("move operation failed to decode path: %w", err)
}
con, key = findObject(doc, path)
if con == nil {
- return errors.Wrapf(ErrMissing, "move operation does not apply: doc is missing destination path: %s", path)
+ return fmt.Errorf("move operation does not apply: doc is missing destination path: %s: %w", path, ErrMissing)
}
err = con.add(key, val)
if err != nil {
- return errors.Wrapf(err, "error in move for path: '%s'", path)
+ return fmt.Errorf("error in move for path: '%s': %w", path, err)
}
return nil
@@ -654,7 +653,7 @@ func (p Patch) move(doc *container, op Operation) error {
func (p Patch) test(doc *container, op Operation) error {
path, err := op.Path()
if err != nil {
- return errors.Wrapf(err, "test operation failed to decode path")
+ return fmt.Errorf("test operation failed to decode path: %w", err)
}
if path == "" {
@@ -673,67 +672,67 @@ func (p Patch) test(doc *container, op Operation) error {
return nil
}
- return errors.Wrapf(ErrTestFailed, "testing value %s failed", path)
+ return fmt.Errorf("testing value %s failed: %w", path, ErrTestFailed)
}
con, key := findObject(doc, path)
if con == nil {
- return errors.Wrapf(ErrMissing, "test operation does not apply: is missing path: %s", path)
+ return fmt.Errorf("test operation does not apply: is missing path: %s: %w", path, ErrMissing)
}
val, err := con.get(key)
if err != nil {
- return errors.Wrapf(err, "error in test for path: '%s'", path)
+ return fmt.Errorf("error in test for path: '%s': %w", path, err)
}
if val == nil {
- if op.value().raw == nil {
+ if op.value() == nil || op.value().raw == nil {
return nil
}
- return errors.Wrapf(ErrTestFailed, "testing value %s failed", path)
+ return fmt.Errorf("testing value %s failed: %w", path, ErrTestFailed)
} else if op.value() == nil {
- return errors.Wrapf(ErrTestFailed, "testing value %s failed", path)
+ return fmt.Errorf("testing value %s failed: %w", path, ErrTestFailed)
}
if val.equal(op.value()) {
return nil
}
- return errors.Wrapf(ErrTestFailed, "testing value %s failed", path)
+ return fmt.Errorf("testing value %s failed: %w", path, ErrTestFailed)
}
func (p Patch) copy(doc *container, op Operation, accumulatedCopySize *int64) error {
from, err := op.From()
if err != nil {
- return errors.Wrapf(err, "copy operation failed to decode from")
+ return fmt.Errorf("copy operation failed to decode from: %w", err)
}
con, key := findObject(doc, from)
if con == nil {
- return errors.Wrapf(ErrMissing, "copy operation does not apply: doc is missing from path: %s", from)
+ return fmt.Errorf("copy operation does not apply: doc is missing from path: %s: %w", from, ErrMissing)
}
val, err := con.get(key)
if err != nil {
- return errors.Wrapf(err, "error in copy for from: '%s'", from)
+ return fmt.Errorf("error in copy for from: '%s': %w", from, err)
}
path, err := op.Path()
if err != nil {
- return errors.Wrapf(ErrMissing, "copy operation failed to decode path")
+ return fmt.Errorf("copy operation failed to decode path: %w", ErrMissing)
}
con, key = findObject(doc, path)
if con == nil {
- return errors.Wrapf(ErrMissing, "copy operation does not apply: doc is missing destination path: %s", path)
+ return fmt.Errorf("copy operation does not apply: doc is missing destination path: %s: %w", path, ErrMissing)
}
valCopy, sz, err := deepCopy(val)
if err != nil {
- return errors.Wrapf(err, "error while performing deep copy")
+ return fmt.Errorf("error while performing deep copy: %w", err)
}
(*accumulatedCopySize) += int64(sz)
@@ -743,7 +742,7 @@ func (p Patch) copy(doc *container, op Operation, accumulatedCopySize *int64) er
err = con.add(key, valCopy)
if err != nil {
- return errors.Wrapf(err, "error while adding value during copy")
+ return fmt.Errorf("error while adding value during copy: %w", err)
}
return nil
diff --git a/etcd/vendor/modules.txt b/etcd/vendor/modules.txt
index 80731d13e3..bc4211bc99 100644
--- a/etcd/vendor/modules.txt
+++ b/etcd/vendor/modules.txt
@@ -191,12 +191,12 @@ github.com/openshift/build-machinery-go/make/targets/golang
github.com/openshift/build-machinery-go/make/targets/openshift
github.com/openshift/build-machinery-go/make/targets/openshift/operator
github.com/openshift/build-machinery-go/scripts
-# github.com/openshift/library-go v0.0.0-20251112091634-ab97ebb73f0f
+# github.com/openshift/library-go v0.0.0-20260121132910-dc3a1c884c04
## explicit; go 1.24.0
github.com/openshift/library-go/pkg/crypto
github.com/openshift/library-go/pkg/operator/apiserver/audit
-# github.com/openshift/microshift v0.0.0 => ../
-## explicit; go 1.24.0
+# github.com/openshift/microshift v0.0.0-00010101000000-000000000000 => ../
+## explicit; go 1.25.0
github.com/openshift/microshift/pkg/config
github.com/openshift/microshift/pkg/config/apiserver
github.com/openshift/microshift/pkg/util
@@ -241,7 +241,7 @@ github.com/sirupsen/logrus
# github.com/soheilhy/cmux v0.1.5
## explicit; go 1.11
github.com/soheilhy/cmux
-# github.com/spf13/cobra v1.9.1
+# github.com/spf13/cobra v1.10.0
## explicit; go 1.15
github.com/spf13/cobra
# github.com/spf13/pflag v1.0.10
@@ -450,18 +450,18 @@ go.uber.org/zap/internal/pool
go.uber.org/zap/internal/stacktrace
go.uber.org/zap/zapcore
go.uber.org/zap/zapgrpc
-# go.yaml.in/yaml/v2 v2.4.2
+# go.yaml.in/yaml/v2 v2.4.3
## explicit; go 1.15
go.yaml.in/yaml/v2
# go.yaml.in/yaml/v3 v3.0.4
## explicit; go 1.16
go.yaml.in/yaml/v3
-# golang.org/x/crypto v0.42.0
+# golang.org/x/crypto v0.45.0
## explicit; go 1.24.0
golang.org/x/crypto/bcrypt
golang.org/x/crypto/blowfish
-# golang.org/x/net v0.43.0
-## explicit; go 1.23.0
+# golang.org/x/net v0.47.0
+## explicit; go 1.24.0
golang.org/x/net/context
golang.org/x/net/html
golang.org/x/net/html/atom
@@ -479,19 +479,19 @@ golang.org/x/net/websocket
## explicit; go 1.23.0
golang.org/x/oauth2
golang.org/x/oauth2/internal
-# golang.org/x/sync v0.17.0
+# golang.org/x/sync v0.18.0
## explicit; go 1.24.0
golang.org/x/sync/errgroup
-# golang.org/x/sys v0.36.0
+# golang.org/x/sys v0.38.0
## explicit; go 1.24.0
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.35.0
+# golang.org/x/term v0.37.0
## explicit; go 1.24.0
golang.org/x/term
-# golang.org/x/text v0.29.0
+# golang.org/x/text v0.31.0
## explicit; go 1.24.0
golang.org/x/text/encoding
golang.org/x/text/encoding/internal
@@ -628,7 +628,7 @@ google.golang.org/protobuf/types/known/fieldmaskpb
google.golang.org/protobuf/types/known/structpb
google.golang.org/protobuf/types/known/timestamppb
google.golang.org/protobuf/types/known/wrapperspb
-# gopkg.in/evanphx/json-patch.v4 v4.12.0
+# gopkg.in/evanphx/json-patch.v4 v4.13.0
## explicit
gopkg.in/evanphx/json-patch.v4
# gopkg.in/inf.v0 v0.9.1
@@ -963,8 +963,8 @@ k8s.io/klog/v2/internal/severity
k8s.io/klog/v2/internal/sloghandler
k8s.io/klog/v2/internal/verbosity
k8s.io/klog/v2/textlogger
-# k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b
-## explicit; go 1.23
+# k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912
+## explicit; go 1.23.0
k8s.io/kube-openapi/pkg/cached
k8s.io/kube-openapi/pkg/common
k8s.io/kube-openapi/pkg/handler3
@@ -995,7 +995,7 @@ k8s.io/utils/exec
k8s.io/utils/internal/third_party/forked/golang/net
k8s.io/utils/net
k8s.io/utils/ptr
-# sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8
+# sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730
## explicit; go 1.23
sigs.k8s.io/json
sigs.k8s.io/json/internal/golang/encoding/json
diff --git a/etcd/vendor/sigs.k8s.io/json/internal/golang/encoding/json/decode.go b/etcd/vendor/sigs.k8s.io/json/internal/golang/encoding/json/decode.go
index d538ac119b..3fe528bbf3 100644
--- a/etcd/vendor/sigs.k8s.io/json/internal/golang/encoding/json/decode.go
+++ b/etcd/vendor/sigs.k8s.io/json/internal/golang/encoding/json/decode.go
@@ -52,8 +52,8 @@ import (
// - bool, for JSON booleans
// - float64, for JSON numbers
// - string, for JSON strings
-// - []interface{}, for JSON arrays
-// - map[string]interface{}, for JSON objects
+// - []any, for JSON arrays
+// - map[string]any, for JSON objects
// - nil for JSON null
//
// To unmarshal a JSON array into a slice, Unmarshal resets the slice length
@@ -117,9 +117,6 @@ func Unmarshal(data []byte, v any, opts ...UnmarshalOpt) error {
// The input can be assumed to be a valid encoding of
// a JSON value. UnmarshalJSON must copy the JSON data
// if it wishes to retain the data after returning.
-//
-// By convention, to approximate the behavior of [Unmarshal] itself,
-// Unmarshalers implement UnmarshalJSON([]byte("null")) as a no-op.
type Unmarshaler interface {
UnmarshalJSON([]byte) error
}
@@ -132,7 +129,7 @@ type UnmarshalTypeError struct {
Type reflect.Type // type of Go value it could not be assigned to
Offset int64 // error occurred after reading Offset bytes
Struct string // name of the struct type containing the field
- Field string // the full path from root node to the field
+ Field string // the full path from root node to the field, include embedded struct
}
func (e *UnmarshalTypeError) Error() string {
@@ -281,7 +278,11 @@ func (d *decodeState) addErrorContext(err error) error {
switch err := err.(type) {
case *UnmarshalTypeError:
err.Struct = d.errorContext.Struct.Name()
- err.Field = strings.Join(d.errorContext.FieldStack, ".")
+ fieldStack := d.errorContext.FieldStack
+ if err.Field != "" {
+ fieldStack = append(fieldStack, err.Field)
+ }
+ err.Field = strings.Join(fieldStack, ".")
}
}
return err
@@ -492,9 +493,9 @@ func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnm
}
// Prevent infinite loop if v is an interface pointing to its own address:
- // var v interface{}
+ // var v any
// v = &v
- if v.Elem().Kind() == reflect.Interface && v.Elem().Elem() == v {
+ if v.Elem().Kind() == reflect.Interface && v.Elem().Elem().Equal(v) {
v = v.Elem()
break
}
@@ -784,7 +785,10 @@ func (d *decodeState) object(v reflect.Value) error {
}
subv = v
destring = f.quoted
- for _, i := range f.index {
+ if d.errorContext == nil {
+ d.errorContext = new(errorContext)
+ }
+ for i, ind := range f.index {
if subv.Kind() == reflect.Pointer {
if subv.IsNil() {
// If a struct embeds a pointer to an unexported type,
@@ -804,13 +808,16 @@ func (d *decodeState) object(v reflect.Value) error {
}
subv = subv.Elem()
}
- subv = subv.Field(i)
- }
- if d.errorContext == nil {
- d.errorContext = new(errorContext)
+ if i < len(f.index)-1 {
+ d.errorContext.FieldStack = append(
+ d.errorContext.FieldStack,
+ subv.Type().Field(ind).Name,
+ )
+ }
+ subv = subv.Field(ind)
}
- d.errorContext.FieldStack = append(d.errorContext.FieldStack, f.name)
d.errorContext.Struct = t
+ d.errorContext.FieldStack = append(d.errorContext.FieldStack, f.name)
d.appendStrictFieldStackKey(f.name)
} else if d.disallowUnknownFields {
d.saveStrictError(d.newFieldError(unknownStrictErrType, string(key)))
@@ -1118,7 +1125,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
// in an empty interface. They are not strictly necessary,
// but they avoid the weight of reflection in this common case.
-// valueInterface is like value but returns interface{}
+// valueInterface is like value but returns any.
func (d *decodeState) valueInterface() (val any) {
switch d.opcode {
default:
@@ -1135,7 +1142,7 @@ func (d *decodeState) valueInterface() (val any) {
return
}
-// arrayInterface is like array but returns []interface{}.
+// arrayInterface is like array but returns []any.
func (d *decodeState) arrayInterface() []any {
origStrictFieldStackLen := len(d.strictFieldStack)
defer func() {
@@ -1170,7 +1177,7 @@ func (d *decodeState) arrayInterface() []any {
return v
}
-// objectInterface is like object but returns map[string]interface{}.
+// objectInterface is like object but returns map[string]any.
func (d *decodeState) objectInterface() map[string]any {
origStrictFieldStackLen := len(d.strictFieldStack)
defer func() {
diff --git a/etcd/vendor/sigs.k8s.io/json/internal/golang/encoding/json/encode.go b/etcd/vendor/sigs.k8s.io/json/internal/golang/encoding/json/encode.go
index eb73bff58b..4e3a1a2f10 100644
--- a/etcd/vendor/sigs.k8s.io/json/internal/golang/encoding/json/encode.go
+++ b/etcd/vendor/sigs.k8s.io/json/internal/golang/encoding/json/encode.go
@@ -71,8 +71,8 @@ import (
//
// The "omitempty" option specifies that the field should be omitted
// from the encoding if the field has an empty value, defined as
-// false, 0, a nil pointer, a nil interface value, and any empty array,
-// slice, map, or string.
+// false, 0, a nil pointer, a nil interface value, and any array,
+// slice, map, or string of length zero.
//
// As a special case, if the field tag is "-", the field is always omitted.
// Note that a field with name "-" can still be generated using the tag "-,".
@@ -98,6 +98,17 @@ import (
// // Field appears in JSON as key "-".
// Field int `json:"-,"`
//
+// The "omitzero" option specifies that the field should be omitted
+// from the encoding if the field has a zero value, according to rules:
+//
+// 1) If the field type has an "IsZero() bool" method, that will be used to
+// determine whether the value is zero.
+//
+// 2) Otherwise, the value is zero if it is the zero value for its type.
+//
+// If both "omitempty" and "omitzero" are specified, the field will be omitted
+// if the value is either empty or zero (or both).
+//
// The "string" option signals that a field is stored as JSON inside a
// JSON-encoded string. It applies only to fields of string, floating point,
// integer, or boolean types. This extra level of encoding is sometimes used
@@ -690,7 +701,8 @@ FieldLoop:
fv = fv.Field(i)
}
- if f.omitEmpty && isEmptyValue(fv) {
+ if (f.omitEmpty && isEmptyValue(fv)) ||
+ (f.omitZero && (f.isZero == nil && fv.IsZero() || (f.isZero != nil && f.isZero(fv)))) {
continue
}
e.WriteByte(next)
@@ -808,7 +820,7 @@ func (se sliceEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
// Here we use a struct to memorize the pointer to the first element of the slice
// and its length.
ptr := struct {
- ptr interface{} // always an unsafe.Pointer, but avoids a dependency on package unsafe
+ ptr any // always an unsafe.Pointer, but avoids a dependency on package unsafe
len int
}{v.UnsafePointer(), v.Len()}
if _, ok := e.ptrSeen[ptr]; ok {
@@ -1039,11 +1051,19 @@ type field struct {
index []int
typ reflect.Type
omitEmpty bool
+ omitZero bool
+ isZero func(reflect.Value) bool
quoted bool
encoder encoderFunc
}
+type isZeroer interface {
+ IsZero() bool
+}
+
+var isZeroerType = reflect.TypeFor[isZeroer]()
+
// typeFields returns a list of fields that JSON should recognize for the given type.
// The algorithm is breadth-first search over the set of structs to include - the top struct
// and then any reachable anonymous structs.
@@ -1135,6 +1155,7 @@ func typeFields(t reflect.Type) structFields {
index: index,
typ: ft,
omitEmpty: opts.Contains("omitempty"),
+ omitZero: opts.Contains("omitzero"),
quoted: quoted,
}
field.nameBytes = []byte(field.name)
@@ -1144,6 +1165,40 @@ func typeFields(t reflect.Type) structFields {
field.nameEscHTML = `"` + string(nameEscBuf) + `":`
field.nameNonEsc = `"` + field.name + `":`
+ if field.omitZero {
+ t := sf.Type
+ // Provide a function that uses a type's IsZero method.
+ switch {
+ case t.Kind() == reflect.Interface && t.Implements(isZeroerType):
+ field.isZero = func(v reflect.Value) bool {
+ // Avoid panics calling IsZero on a nil interface or
+ // non-nil interface with nil pointer.
+ return v.IsNil() ||
+ (v.Elem().Kind() == reflect.Pointer && v.Elem().IsNil()) ||
+ v.Interface().(isZeroer).IsZero()
+ }
+ case t.Kind() == reflect.Pointer && t.Implements(isZeroerType):
+ field.isZero = func(v reflect.Value) bool {
+ // Avoid panics calling IsZero on nil pointer.
+ return v.IsNil() || v.Interface().(isZeroer).IsZero()
+ }
+ case t.Implements(isZeroerType):
+ field.isZero = func(v reflect.Value) bool {
+ return v.Interface().(isZeroer).IsZero()
+ }
+ case reflect.PointerTo(t).Implements(isZeroerType):
+ field.isZero = func(v reflect.Value) bool {
+ if !v.CanAddr() {
+ // Temporarily box v so we can take the address.
+ v2 := reflect.New(v.Type()).Elem()
+ v2.Set(v)
+ v = v2
+ }
+ return v.Addr().Interface().(isZeroer).IsZero()
+ }
+ }
+ }
+
fields = append(fields, field)
if count[f.typ] > 1 {
// If there were multiple instances, add a second,
diff --git a/etcd/vendor/sigs.k8s.io/json/internal/golang/encoding/json/stream.go b/etcd/vendor/sigs.k8s.io/json/internal/golang/encoding/json/stream.go
index 48fc4d9453..cc2108b927 100644
--- a/etcd/vendor/sigs.k8s.io/json/internal/golang/encoding/json/stream.go
+++ b/etcd/vendor/sigs.k8s.io/json/internal/golang/encoding/json/stream.go
@@ -31,8 +31,8 @@ func NewDecoder(r io.Reader) *Decoder {
return &Decoder{r: r}
}
-// UseNumber causes the Decoder to unmarshal a number into an interface{} as a
-// [Number] instead of as a float64.
+// UseNumber causes the Decoder to unmarshal a number into an
+// interface value as a [Number] instead of as a float64.
func (dec *Decoder) UseNumber() { dec.d.useNumber = true }
// DisallowUnknownFields causes the Decoder to return an error when the destination
diff --git a/go.mod b/go.mod
index d9ee75e293..c1aa920ad9 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
module github.com/openshift/microshift
-go 1.24.0
+go 1.25.0
require (
github.com/apparentlymart/go-cidr v1.1.0
@@ -10,17 +10,17 @@ require (
github.com/openshift/api v0.0.0-20251214014457-bfa868a22401
github.com/openshift/build-machinery-go v0.0.0-20251023084048-5d77c1a5e5af
github.com/openshift/client-go v0.0.0-20251205093018-96a6cbc1420c
- github.com/openshift/library-go v0.0.0-20251112091634-ab97ebb73f0f
+ github.com/openshift/library-go v0.0.0-20260121132910-dc3a1c884c04
github.com/pkg/errors v0.9.1 // indirect
- github.com/spf13/cobra v1.9.1
+ github.com/spf13/cobra v1.10.0
github.com/spf13/pflag v1.0.10
github.com/stretchr/testify v1.11.1
github.com/vishvananda/netlink v1.3.1
- go.etcd.io/etcd/client/pkg/v3 v3.6.4
- go.etcd.io/etcd/client/v3 v3.6.4
- golang.org/x/sys v0.36.0
+ go.etcd.io/etcd/client/pkg/v3 v3.6.5
+ go.etcd.io/etcd/client/v3 v3.6.5
+ golang.org/x/sys v0.38.0
gopkg.in/yaml.v3 v3.0.1
- k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b
+ k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912
sigs.k8s.io/yaml v1.6.0
)
@@ -32,7 +32,7 @@ require (
github.com/gogo/protobuf v1.3.2
github.com/golang/snappy v0.0.4
github.com/openshift/cluster-policy-controller v0.0.0-20251120141414-8b775487512f
- github.com/openshift/route-controller-manager v0.0.0-20260127173744-2b9e93a5f0fc
+ github.com/openshift/route-controller-manager v0.0.0-20260211095309-624742d93f3a
github.com/prometheus/client_model v0.6.2
github.com/prometheus/common v0.66.1
github.com/prometheus/prometheus v0.302.1
@@ -57,6 +57,7 @@ require (
require (
cel.dev/expr v0.24.0 // indirect
+ cyphar.com/go-pathrs v0.2.1 // indirect
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab // indirect
@@ -76,7 +77,7 @@ require (
github.com/containerd/ttrpc v1.2.6 // indirect
github.com/containerd/typeurl/v2 v2.2.2 // indirect
github.com/coreos/go-oidc v2.3.0+incompatible // indirect
- github.com/cyphar/filepath-securejoin v0.5.1 // indirect
+ github.com/cyphar/filepath-securejoin v0.6.0 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/euank/go-kmsg-parser v2.0.0+incompatible // indirect
@@ -100,7 +101,7 @@ require (
github.com/google/btree v1.1.3 // indirect
github.com/google/cadvisor v0.52.1 // indirect
github.com/google/cel-go v0.26.0 // indirect
- github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
+ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
@@ -126,7 +127,7 @@ require (
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/opencontainers/runc v1.2.8 // indirect
github.com/opencontainers/runtime-spec v1.2.0 // indirect
- github.com/opencontainers/selinux v1.12.0 // indirect
+ github.com/opencontainers/selinux v1.13.0 // indirect
github.com/openshift/apiserver-library-go v0.0.0-20251015164739-79d04067059d // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pquerna/cachecontrol v0.1.0 // indirect
@@ -141,7 +142,7 @@ require (
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful v0.44.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect
- go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect
+ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
go.opentelemetry.io/otel v1.37.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect
@@ -150,14 +151,14 @@ require (
go.opentelemetry.io/otel/trace v1.37.0 // indirect
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
go.uber.org/atomic v1.11.0 // indirect
- go.yaml.in/yaml/v2 v2.4.2 // indirect
+ go.yaml.in/yaml/v2 v2.4.3 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
- golang.org/x/crypto v0.42.0 // indirect
+ golang.org/x/crypto v0.45.0 // indirect
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
- golang.org/x/term v0.35.0 // indirect
+ golang.org/x/term v0.37.0 // indirect
golang.org/x/time v0.9.0 // indirect
- gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
+ gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
@@ -177,7 +178,7 @@ require (
k8s.io/mount-utils v1.34.2 // indirect
k8s.io/pod-security-admission v1.34.2 // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect
- sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
+ sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect
)
@@ -203,21 +204,21 @@ require (
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/vishvananda/netns v0.0.5 // indirect
- go.etcd.io/etcd/api/v3 v3.6.4 // indirect
+ go.etcd.io/etcd/api/v3 v3.6.5 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
- golang.org/x/mod v0.27.0 // indirect
- golang.org/x/net v0.43.0 // indirect
- golang.org/x/sync v0.17.0 // indirect
- golang.org/x/text v0.29.0 // indirect
- golang.org/x/tools v0.36.0 // indirect
+ golang.org/x/mod v0.29.0 // indirect
+ golang.org/x/net v0.47.0 // indirect
+ golang.org/x/sync v0.18.0 // indirect
+ golang.org/x/text v0.31.0 // indirect
+ golang.org/x/tools v0.38.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250804133106-a7a43d27e69b // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1 // indirect
google.golang.org/grpc v1.76.0 // indirect
google.golang.org/protobuf v1.36.8 // indirect
k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f // indirect
k8s.io/klog/v2 v2.130.1
- k8s.io/kubernetes v1.34.2
+ k8s.io/kubernetes v1.35.0
)
replace (
diff --git a/go.sum b/go.sum
index 8dd726435d..76a141d650 100644
--- a/go.sum
+++ b/go.sum
@@ -1,5 +1,7 @@
cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY=
cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
+cyphar.com/go-pathrs v0.2.1 h1:9nx1vOgwVvX1mNBWDu93+vaceedpbsDqo+XuBGL40b8=
+cyphar.com/go-pathrs v0.2.1/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
@@ -68,8 +70,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
-github.com/cyphar/filepath-securejoin v0.5.1 h1:eYgfMq5yryL4fbWfkLpFFy2ukSELzaJOTaUTuh+oF48=
-github.com/cyphar/filepath-securejoin v0.5.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
+github.com/cyphar/filepath-securejoin v0.6.0 h1:BtGB77njd6SVO6VztOHfPxKitJvd/VPT+OFBFMOi1Is=
+github.com/cyphar/filepath-securejoin v0.6.0/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
@@ -159,8 +161,8 @@ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
-github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
-github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
+github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
+github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
@@ -267,8 +269,8 @@ github.com/opencontainers/runc v1.2.8 h1:RnEICeDReapbZ5lZEgHvj7E9Q3Eex9toYmaGBsb
github.com/opencontainers/runc v1.2.8/go.mod h1:cC0YkmZcuvr+rtBZ6T7NBoVbMGNAdLa/21vIElJDOzI=
github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
-github.com/opencontainers/selinux v1.12.0 h1:6n5JV4Cf+4y0KNXW48TLj5DwfXpvWlxXplUkdTrmPb8=
-github.com/opencontainers/selinux v1.12.0/go.mod h1:BTPX+bjVbWGXw7ZZWUbdENt8w0htPSrlgOOysQaU62U=
+github.com/opencontainers/selinux v1.13.0 h1:Zza88GWezyT7RLql12URvoxsbLfjFx988+LGaWfbL84=
+github.com/opencontainers/selinux v1.13.0/go.mod h1:XxWTed+A/s5NNq4GmYScVy+9jzXhGBVEOAyucdRUY8s=
github.com/openshift/api v0.0.0-20251214014457-bfa868a22401 h1:goMf6pBtRFSQaVElFk6K+GIAqnv7O84p7PJHH6pDz/E=
github.com/openshift/api v0.0.0-20251214014457-bfa868a22401/go.mod h1:d5uzF0YN2nQQFA0jIEWzzOZ+edmo6wzlGLvx5Fhz4uY=
github.com/openshift/apiserver-library-go v0.0.0-20251015164739-79d04067059d h1:Mfya3RxHWvidOrKyHj3bmFn5x2B89DLZIvDAhwm+C2s=
@@ -281,12 +283,12 @@ github.com/openshift/cluster-policy-controller v0.0.0-20251120141414-8b775487512
github.com/openshift/cluster-policy-controller v0.0.0-20251120141414-8b775487512f/go.mod h1:LXi/198uMe/91uydJ/yHz+jS66JCP1DtSonVDFhVVPs=
github.com/openshift/kubernetes-kube-storage-version-migrator v0.0.3-0.20260105155255-73b468abf83d h1:BlRqHWLT8GtikpEbhReHR+EgZIJ9o/wo+JDP7XC1qis=
github.com/openshift/kubernetes-kube-storage-version-migrator v0.0.3-0.20260105155255-73b468abf83d/go.mod h1:o5cKv/pQ+exEYKq97WapNa5cxSPxuwBezHZHNW5RNRo=
-github.com/openshift/library-go v0.0.0-20251112091634-ab97ebb73f0f h1:r1pLosA7z3+t+lzW29FU54sg4/pAWu+lsKD0L5Gx3wg=
-github.com/openshift/library-go v0.0.0-20251112091634-ab97ebb73f0f/go.mod h1:ErDfiIrPHH+menTP/B4LKd0nxFDdvCbTamAc6SWMIh8=
+github.com/openshift/library-go v0.0.0-20260121132910-dc3a1c884c04 h1:Fm9C8pT4l6VjpdqdhI1cBX9Y3D3S+rFxptVhCPBbMAI=
+github.com/openshift/library-go v0.0.0-20260121132910-dc3a1c884c04/go.mod h1:nIzWQQE49XbiKizVnVOip9CEB7HJ0hoJwNi3g3YKnKc=
github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20251001123353-fd5b1fb35db1 h1:PMTgifBcBRLJJiM+LgSzPDTk9/Rx4qS09OUrfpY6GBQ=
github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20251001123353-fd5b1fb35db1/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
-github.com/openshift/route-controller-manager v0.0.0-20260127173744-2b9e93a5f0fc h1:Dt1sz1Dthy5bRMNin/URQ8NJKLU36D3Qn1l/XJu6pLY=
-github.com/openshift/route-controller-manager v0.0.0-20260127173744-2b9e93a5f0fc/go.mod h1:/tw1PYHkUdzPG+EuC+ANJdDD81Ik2pPzYjLBZhyzyME=
+github.com/openshift/route-controller-manager v0.0.0-20260211095309-624742d93f3a h1:jBmugEVHpoRmyNBFb7ZBLeurE5+snu9NXS6bf57iiqA=
+github.com/openshift/route-controller-manager v0.0.0-20260211095309-624742d93f3a/go.mod h1:KNxrLlGIh4j2iUAOax5Y9f5rN3vIo8w9QTGKHEQlvFo=
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
@@ -315,8 +317,8 @@ github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
-github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
-github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
+github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
+github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
@@ -325,9 +327,9 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
-github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
-github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
-github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/cobra v1.10.0 h1:a5/WeUlSDCvV5a45ljW2ZFtV0bTDpkfSAj3uqB6Sc+0=
+github.com/spf13/cobra v1.10.0/go.mod h1:9dhySC7dnTtEiqzmqfkLj47BslqLCUPMXjG2lj/NgoE=
+github.com/spf13/pflag v1.0.8/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/squat/generic-device-plugin v0.0.0-20251019101956-043a51e18f31 h1:wPJNupO/W9VJkwf/5vVnEReuS3pf5u+V+RGv6TOPrLM=
@@ -363,12 +365,12 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.4.2 h1:IrUHp260R8c+zYx/Tm8QZr04CX+qWS5PGfPdevhdm1I=
go.etcd.io/bbolt v1.4.2/go.mod h1:Is8rSHO/b4f3XigBC0lL0+4FwAQv3HXEEIgFMuKHceM=
-go.etcd.io/etcd/api/v3 v3.6.4 h1:7F6N7toCKcV72QmoUKa23yYLiiljMrT4xCeBL9BmXdo=
-go.etcd.io/etcd/api/v3 v3.6.4/go.mod h1:eFhhvfR8Px1P6SEuLT600v+vrhdDTdcfMzmnxVXXSbk=
-go.etcd.io/etcd/client/pkg/v3 v3.6.4 h1:9HBYrjppeOfFjBjaMTRxT3R7xT0GLK8EJMVC4xg6ok0=
-go.etcd.io/etcd/client/pkg/v3 v3.6.4/go.mod h1:sbdzr2cl3HzVmxNw//PH7aLGVtY4QySjQFuaCgcRFAI=
-go.etcd.io/etcd/client/v3 v3.6.4 h1:YOMrCfMhRzY8NgtzUsHl8hC2EBSnuqbR3dh84Uryl7A=
-go.etcd.io/etcd/client/v3 v3.6.4/go.mod h1:jaNNHCyg2FdALyKWnd7hxZXZxZANb0+KGY+YQaEMISo=
+go.etcd.io/etcd/api/v3 v3.6.5 h1:pMMc42276sgR1j1raO/Qv3QI9Af/AuyQUW6CBAWuntA=
+go.etcd.io/etcd/api/v3 v3.6.5/go.mod h1:ob0/oWA/UQQlT1BmaEkWQzI0sJ1M0Et0mMpaABxguOQ=
+go.etcd.io/etcd/client/pkg/v3 v3.6.5 h1:Duz9fAzIZFhYWgRjp/FgNq2gO1jId9Yae/rLn3RrBP8=
+go.etcd.io/etcd/client/pkg/v3 v3.6.5/go.mod h1:8Wx3eGRPiy0qOFMZT/hfvdos+DjEaPxdIDiCDUv/FQk=
+go.etcd.io/etcd/client/v3 v3.6.5 h1:yRwZNFBx/35VKHTcLDeO7XVLbCBFbPi+XV4OC3QJf2U=
+go.etcd.io/etcd/client/v3 v3.6.5/go.mod h1:ZqwG/7TAFZ0BJ0jXRPoJjKQJtbFo/9NIY8uoFFKcCyo=
go.etcd.io/etcd/pkg/v3 v3.6.4 h1:fy8bmXIec1Q35/jRZ0KOes8vuFxbvdN0aAFqmEfJZWA=
go.etcd.io/etcd/pkg/v3 v3.6.4/go.mod h1:kKcYWP8gHuBRcteyv6MXWSN0+bVMnfgqiHueIZnKMtE=
go.etcd.io/etcd/server/v3 v3.6.4 h1:LsCA7CzjVt+8WGrdsnh6RhC0XqCsLkBly3ve5rTxMAU=
@@ -381,8 +383,8 @@ go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelr
go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful v0.44.0/go.mod h1:uq8DrRaen3suIWTpdR/JNHCGpurSvMv9D5Nr5CU5TXc=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
go.opentelemetry.io/contrib/propagators/b3 v1.19.0 h1:ulz44cpm6V5oAeg5Aw9HyqGFMS6XM7untlMEhD7YzzA=
go.opentelemetry.io/contrib/propagators/b3 v1.19.0/go.mod h1:OzCmE2IVS+asTI+odXQstRGVfXQ4bXv9nMBRK0nNyqQ=
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
@@ -409,34 +411,34 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
-go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
-go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
+go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
+go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
-golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
+golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
+golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-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/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
+golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
-golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
+golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
+golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
-golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
+golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
+golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -447,22 +449,22 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
-golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
-golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
-golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
+golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
+golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
+golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
+golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
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.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
-golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
+golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
+golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-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 v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
+golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
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=
@@ -484,8 +486,8 @@ google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXn
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
-gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
-gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
+gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo=
+gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs=
gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
@@ -499,14 +501,14 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f h1:SLb+kxmzfA87x4E4brQzB33VBbT2+x7Zq9ROIHmGn9Q=
k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU=
-k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA=
-k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts=
+k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE=
+k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ=
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck=
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
-sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
-sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
+sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
+sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/kustomize/api v0.20.1 h1:iWP1Ydh3/lmldBnH/S5RXgT98vWYMaTUL1ADcr+Sv7I=
sigs.k8s.io/kustomize/api v0.20.1/go.mod h1:t6hUFxO+Ph0VxIk1sKp1WS0dOjbPCtLJ4p8aADLwqjM=
sigs.k8s.io/kustomize/kyaml v0.20.1 h1:PCMnA2mrVbRP3NIB6v9kYCAc38uvFLVs8j/CD567A78=
diff --git a/packaging/crio.conf.d/10-microshift_amd64.conf b/packaging/crio.conf.d/10-microshift_amd64.conf
index 2a2212312c..00cc8bed3b 100644
--- a/packaging/crio.conf.d/10-microshift_amd64.conf
+++ b/packaging/crio.conf.d/10-microshift_amd64.conf
@@ -2,6 +2,6 @@
# for community builds on top of OKD, this setting has no effect
[crio.image]
global_auth_file="/etc/crio/openshift-pull-secret"
-pause_image = "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:89d38d074f3fefeafe47171f755345c5ef521324af0f32683bf9a69068ee6d90"
+pause_image = "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:7513507ca94673ee17e2bde9edd2335b8bea7a72ac17a32ba0d60808742b7527"
pause_image_auth_file = "/etc/crio/openshift-pull-secret"
pause_command = "/usr/bin/pod"
diff --git a/packaging/crio.conf.d/10-microshift_arm64.conf b/packaging/crio.conf.d/10-microshift_arm64.conf
index 136304104c..16c0a3b990 100644
--- a/packaging/crio.conf.d/10-microshift_arm64.conf
+++ b/packaging/crio.conf.d/10-microshift_arm64.conf
@@ -2,6 +2,6 @@
# for community builds on top of OKD, this setting has no effect
[crio.image]
global_auth_file="/etc/crio/openshift-pull-secret"
-pause_image = "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:e95d5626e35158343ffe994f18588fb91a6baa7ce513b8a17e095d16e6b0293c"
+pause_image = "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f119f20eded8102499fb9a65a990d7e3e8e47f866efe70db6597718dd2a42b20"
pause_image_auth_file = "/etc/crio/openshift-pull-secret"
pause_command = "/usr/bin/pod"
diff --git a/pkg/assets/unstructured.go b/pkg/assets/unstructured.go
index 2450e17b29..a65f2cf71e 100644
--- a/pkg/assets/unstructured.go
+++ b/pkg/assets/unstructured.go
@@ -52,14 +52,6 @@ var configClientCache = make(map[string]configClientCacheEntry, 1)
var configClientCacheLock sync.RWMutex
type unstructuredClient struct {
- base dynamic.Interface
- mapper meta.ResettableRESTMapper
-
- Client dynamic.ResourceInterface
- Discovery discovery.AggregatedDiscoveryInterface
-
- unstructured *unstructured.Unstructured
-
// modify is a function that modifies the existing object based on the required object.
// The first argument is a pointer to a boolean that should be set to true if the object was modified.
// i.e. `*modified = true`
@@ -68,6 +60,14 @@ type unstructuredClient struct {
// If Not set, the object will only have its metadata fields updated.
// If set, the object will be modified based on the function.
ModifyOnExists
+
+ base dynamic.Interface
+ mapper meta.ResettableRESTMapper
+
+ Client dynamic.ResourceInterface
+ Discovery discovery.AggregatedDiscoveryInterface
+
+ unstructured *unstructured.Unstructured
}
func unstructuredConfigAndClient(kubeconfigPath string) (configClientCacheEntry, error) {
diff --git a/pkg/cmd/showConfig.go b/pkg/cmd/showConfig.go
index 469f376b46..dd1ef3df98 100644
--- a/pkg/cmd/showConfig.go
+++ b/pkg/cmd/showConfig.go
@@ -12,8 +12,9 @@ import (
)
type showConfigOptions struct {
- Mode string
genericclioptions.IOStreams
+
+ Mode string
}
func NewShowConfigCommand(ioStreams genericclioptions.IOStreams) *cobra.Command {
diff --git a/pkg/cmd/version.go b/pkg/cmd/version.go
index c76b1e017c..193f700573 100644
--- a/pkg/cmd/version.go
+++ b/pkg/cmd/version.go
@@ -14,9 +14,9 @@ import (
)
type VersionOptions struct {
- Output string
-
genericclioptions.IOStreams
+
+ Output string
}
func NewVersionOptions(ioStreams genericclioptions.IOStreams) *VersionOptions {
diff --git a/pkg/components/controllers.go b/pkg/components/controllers.go
index ca18b4d748..e9bdf7af50 100644
--- a/pkg/components/controllers.go
+++ b/pkg/components/controllers.go
@@ -349,7 +349,7 @@ func startDNSController(ctx context.Context, cfg *config.Config, kubeconfigPath
// type list. Also quote/escape any characters that are special to HAProxy (\,', and ").
// See http://cbonte.github.io/haproxy-dconv/2.2/configuration.html#2.2
func getMIMETypes(mimeTypes []operatorv1.CompressionMIMEType) []string {
- mimes := []string{}
+ mimes := make([]string, 0, len(mimeTypes))
for _, m := range mimeTypes {
mimeType := string(m)
diff --git a/pkg/healthcheck/debug_info.go b/pkg/healthcheck/debug_info.go
index cb995139a3..3474c8bd9a 100644
--- a/pkg/healthcheck/debug_info.go
+++ b/pkg/healthcheck/debug_info.go
@@ -129,6 +129,7 @@ type unpulledImage struct {
type failedImage struct {
unpulledImage
+
Message string
}
diff --git a/pkg/mdns/controller.go b/pkg/mdns/controller.go
index 62e7c901ef..43c6640415 100644
--- a/pkg/mdns/controller.go
+++ b/pkg/mdns/controller.go
@@ -16,6 +16,7 @@ import (
type MicroShiftmDNSController struct {
sync.Mutex
+
NodeName string
NodeIP string
KubeConfig string
@@ -127,7 +128,7 @@ func ipInAddrs(ip string, addrs []net.Addr) bool {
}
func addrsToStrings(addrs []net.Addr) []string {
- var ipAddrs = make([]string, 0)
+ var ipAddrs = make([]string, 0, len(addrs))
for _, a := range addrs {
ipAddr, _, _ := net.ParseCIDR(a.String())
diff --git a/pkg/mdns/server/resolver.go b/pkg/mdns/server/resolver.go
index 179c05e704..86ca595c67 100644
--- a/pkg/mdns/server/resolver.go
+++ b/pkg/mdns/server/resolver.go
@@ -26,6 +26,7 @@ const defaultTTL = 120
type Resolver struct {
sync.Mutex
+
domain map[string][]net.IP
}
@@ -38,7 +39,7 @@ func NewResolver() *Resolver {
func (r *Resolver) AddDomain(name string, ipStrs []string) {
r.Lock()
defer r.Unlock()
- var ips = make([]net.IP, 0)
+ var ips = make([]net.IP, 0, len(ipStrs))
for _, ip := range ipStrs {
ips = append(ips, net.ParseIP(ip))
diff --git a/pkg/servicemanager/manager.go b/pkg/servicemanager/manager.go
index 2ec2b0ba63..cf5c049292 100644
--- a/pkg/servicemanager/manager.go
+++ b/pkg/servicemanager/manager.go
@@ -78,7 +78,7 @@ func (m *ServiceManager) Run(ctx context.Context, ready chan<- struct{}, stopped
for _, service := range services {
// Compile a list of ready channels of the service's dependencies (if any).
- depsReadyList := []<-chan struct{}{}
+ depsReadyList := make([]<-chan struct{}, 0, len(service.Dependencies()))
for _, dependency := range service.Dependencies() {
depsReadyList = append(depsReadyList, readyMap[dependency])
}
diff --git a/pkg/telemetry/telemetry.go b/pkg/telemetry/telemetry.go
index e1a9fa44e9..5ffe4f2332 100644
--- a/pkg/telemetry/telemetry.go
+++ b/pkg/telemetry/telemetry.go
@@ -325,12 +325,11 @@ func computeMicroShiftVersionMetric() (Metric, error) {
}
func convertMetricsToWriteRequest(metrics []Metric) *prompb.WriteRequest {
- timeSeriesList := make([]prompb.TimeSeries, 0)
- metricMetadataList := make([]prompb.MetricMetadata, 0)
+ timeSeriesList := make([]prompb.TimeSeries, 0, len(metrics))
+ metricMetadataList := make([]prompb.MetricMetadata, 0, len(metrics))
for _, metric := range metrics {
- labels := []prompb.Label{
- {Name: "__name__", Value: metric.Name},
- }
+ labels := make([]prompb.Label, 0, 1+len(metric.Labels))
+ labels = append(labels, prompb.Label{Name: "__name__", Value: metric.Name})
for _, label := range metric.Labels {
labels = append(labels, prompb.Label{
Name: label.Name,
diff --git a/pkg/util/cryptomaterial/certchains/signers.go b/pkg/util/cryptomaterial/certchains/signers.go
index c78ae6a03b..130b706b34 100644
--- a/pkg/util/cryptomaterial/certchains/signers.go
+++ b/pkg/util/cryptomaterial/certchains/signers.go
@@ -63,6 +63,7 @@ type CertificateSigner struct {
type signedCertificateInfo struct {
CSRInfo
+
tlsConfig *crypto.TLSCertificateConfig
}
@@ -228,7 +229,7 @@ func (s *CertificateSigner) AddToBundles(bundlePaths ...string) error {
return nil
}
-func (s *CertificateSigner) toBuilder() CertificateSignerBuilder { //nolint:ireturn
+func (s *CertificateSigner) toBuilder() CertificateSignerBuilder {
signer := NewCertificateSigner(s.signerName, s.signerDir, s.signerValidity)
for _, subCA := range s.subCAs {
diff --git a/pkg/version/version.go b/pkg/version/version.go
index 2be5fadeb5..befcfd2422 100644
--- a/pkg/version/version.go
+++ b/pkg/version/version.go
@@ -35,6 +35,7 @@ const BuildVariantCommunity = "community"
type Info struct {
version.Info
+
BuildVariant string
Patch string `json:"patch"`
}
diff --git a/scripts/auto-rebase/changelog.txt b/scripts/auto-rebase/changelog.txt
index 8481e43f3e..e69de29bb2 100644
--- a/scripts/auto-rebase/changelog.txt
+++ b/scripts/auto-rebase/changelog.txt
@@ -1,95 +0,0 @@
-- api embedded-component c16ec2bcf089999a012322dbf889c632729dc80d to 81371d13d1fcad175a48627cf11524a94a80c377
- - 43dd9725 2026-02-03T15:18:57Z CodeRabbit should not be looking at openapi generated content
- - b792c564 2026-02-02T12:08:34Z Remove pre 4.20 SDN feature gates
- - fe0f7f81 2026-01-30T12:12:42+01:00 add suggestions
- - f7f52ce3 2026-01-30T11:03:10+01:00 feat: add Insights capability to Insights CRDs
- - 1d800807 2026-01-29T10:29:12-05:00 promote ManagedBootImagesCPMS fg to Default
- - e73ed72f 2026-01-29T09:48:40-05:00 Add CRIOCredentialProviderConfig API
- - 60662b01 2026-01-29T10:55:55Z Remove ProcMountType
- - 7441eb56 2026-01-28T12:06:53+01:00 add suggestions
- - f8a69ad1 2026-01-08T13:08:09+01:00 Fix documentation punctuation and regenerate files
- - 66fff255 2026-01-08T12:23:59+01:00 add prometheusOperatorConfig API
-
-- cluster-csi-snapshot-controller-operator embedded-component 8be3728d7db58111e6efb46f6075698d6b7ec994 to 7b6335396677dfd392dc72e1f1bbb5afcfa74a44
- - f6a61f9 2026-01-27T21:59:36-08:00 Rename replacer func to more generic name
- - 4b3bf71 2026-01-27T21:52:16-08:00 hypershift: Add version annotation to controller Deployments
- - 4cfd73e 2026-01-27T19:40:57-08:00 Bump library-go dependency
- - 90e85d2 2026-01-27T19:40:57-08:00 Add desired-version annotation to controller Deployment
-
-- cluster-ingress-operator embedded-component eeb7347184177d0f0855632bad82398089547e87 to 77901360f18951f2a51d38acd1a07714f9183493
- - b2c8e1c 2026-02-02T15:26:39-05:00 E2E test for internal LB creation
-
-- cluster-kube-apiserver-operator embedded-component 064809665fd54e4c15d3b0c2f6da9fadce715c34 to fecf00cbeaf1fc18178bffddab767ee8f3d7e36f
- - f82dace 2026-01-29T12:46:58-03:00 Bump library-go to get KMS helper
- - 0e25cb4 2026-01-29T12:46:58-03:00 Conditionally add the KMS plugin volume mount to the kube-apiserver container
- - f6a1c91 2026-01-27T17:06:18+01:00 CNTRLPLANE-2563: update wording for major upgrades
-
-- cluster-kube-scheduler-operator embedded-component ed10ad69474b83c568452f59dbd3d943778799d7 to b37b73a87e7a6612f3354c2ffc134a23a0a8c13c
- - d7f76dc 2026-01-27T20:23:53+05:30 Bump dependencies
- - a7a7db7 2026-01-27T20:23:21+05:30 Adds openshift/cluster-kube-scheduler-operator/operator/serial suite to the test ext binary
-
-- cluster-network-operator embedded-component b9a777441ccdbaea524196ecd15aed7e0aa8ab5e to f0bdee37451757734c3e84cb6c0a8646290c4ffa
- - d19cb3f 2026-01-28T20:28:45+01:00 Fix staticcheck QF* and ST* lint issues
- - eba58e4 2026-01-28T20:28:45+01:00 Update golangci-lint config for v2 compatibility
- - 46882d6 2026-01-28T15:29:08+01:00 Fix existing lint errors found by golangci-lint v1
- - 2527aec 2026-01-28T11:51:13Z Remove templating for removed feature gates
- - 9f45d8d 2026-01-27T17:11:09-08:00 avoid flapping Degraded on transient failures
- - ebdaccd 2026-01-27T12:15:46Z Remove references to AdminNetworkPolicy and NetworkSegmentation featuregates
- - 756a7ea 2026-01-26T14:32:35+01:00 OCPBUGS-74401: Remove duplicated openssl parameter
- - 5e9c628 2026-01-12T17:35:27+01:00 CNF-20883: Align templates frrk8s
-
-- etcd embedded-component 806f690e1f140e0aea2eb05ef5f288b756b62895 to 6a0992267004177e385e35b91e186635a644dbfe
- - 4afffb4f 2025-12-18T20:05:04Z Updating ose-etcd-container image to be consistent with ART for 4.22 Reconciling with https://github.com/openshift/ocp-build-data/tree/087d1930e36b609f77d73bd8a313d85c940cff4d/images/ose-etcd.yml
-
-- kubernetes embedded-component e4a4167c40c9ed543c5a80f2e08cc73696f7a4f6 to 9d521311f5fb67dc43f49eeb728ee2c80976835a
- - bb37a6c1a 2026-02-03T09:47:51+01:00 UPSTREAM: 136202: raise kubelet CSI init backoff to cover ~140s DNS delays
- - 5579c3340 2026-01-16T14:19:18-05:00 UPSTREAM: : Added validation to check if OKD featureset is being enabled on OKD clusters
- - 8504fe0c7 2026-01-13T14:38:55-05:00 UPSTREAM: : Vendored API repo
-
-- machine-config-operator embedded-component 1881dab7389ab49e3fbb2eaee17ea74b4f84b2ad to 067395ed863e0254c4e7ce85bf8bce7e464778bb
- - df7f0605 2026-02-03T15:52:07-05:00 Fix OSImageStream validating admission policies for OKD
- - 29a85663 2026-02-01T21:26:26-08:00 OKD: Pass TAGS argument to the machine-config-controller image build
- - a9ea6555 2026-01-30T13:32:42-05:00 daemon: migrate legacy direct runGetOut references to use the CommandRunner interface
- - 23c15b3e 2026-01-29T18:44:08Z MCO-2090: migrate nodedisruptionpolicy tests from the private repository to MCO repository
- - 0b7af4aa 2026-01-29T08:36:25-05:00 AGENT-1424: Add e2e test for IRI deletion
- - 56825a4f 2026-01-28T13:24:29-05:00 docs: add bootstrap e2e guide
- - 64001b7a 2026-01-27T15:38:19-06:00 fixes exposure of sensitive data in log files
- - e3841fb7 2026-01-27T10:34:18-05:00 add VAP for CPMS boot image updates
- - 28f9c724 2026-01-27T12:44:31+01:00 MCO-2088: Remove wasm extension
- - a223cc74 2026-01-23T10:15:20-05:00 add iri prefix to root certificate file
- - 5b44ac92 2026-01-23T10:15:08-05:00 replaced controller clients with the related listers
- - c6271f42 2026-01-12T09:44:27-05:00 controller: refactor helpers to get machines by state
-
-- openshift-controller-manager embedded-component aaacf2be3860ec3609e6031527a6ffca4f282ba7 to 19ac71374ea7d42957fe0eb3cc6d38679cc257e1
- - d39fedb 2026-02-02T20:41:05+01:00 CNTRLPLANE-2620: bump github.com/openshift/library-go
-
-- operator-framework-olm embedded-component 526cde8d70dc640972eab717f80b42b66e8dff15 to fae41b2724eeab7a0e9b1ad89408bbbb36516fe2
- - 7c903b19 2026-02-04T13:39:02+08:00 continue to adjust case per collect-profiles change
- - 0fc3cdb2 2026-02-03T16:16:18+08:00 UPSTREAM: : automate OCP-87276
- - 0085e3c9 2026-02-03T00:13:13-05:00 Remove the collect-profiles job
- - 04ce50ea 2026-02-03T10:45:55+08:00 UPSTREAM: : remove redhat-marketplace catalog
- - ec98e0d8 2026-02-03T09:08:53+08:00 change to check collect-profile networkpolicy dynamically
- - d8f66874 2026-01-28T14:38:57+08:00 Add retry logic for SNO cluster detection in leader election configuration
-
-- oc image-amd64 430c82293109e23f3caaf9ba60e5affd2d5356f5 to 7e80dbab5a9ce563cd4f78f2874f18e4664767f5
- - 08d5f27a 2026-01-30T14:17:04+01:00 expose: Fix labels not being added to route
- - e87384f5 2026-01-29T20:38:10-05:00 Revert "CNTRLPLANE-2656:Migrating oc cli tests to ote"
- - 9619e215 2026-01-28T11:01:38-05:00 OSDOCS#18071: Updating CLI docs templates to include a required abstract/short description
- - 63b9258c 2026-01-28T19:41:37+05:30 removing bindata.go
- - c423f7b7 2026-01-21T12:39:18+05:30 Removed sos cases
-
-- kubernetes image-amd64 e4a4167c40c9ed543c5a80f2e08cc73696f7a4f6 to 9d521311f5fb67dc43f49eeb728ee2c80976835a
- - bb37a6c1a 2026-02-03T09:47:51+01:00 UPSTREAM: 136202: raise kubelet CSI init backoff to cover ~140s DNS delays
- - 5579c3340 2026-01-16T14:19:18-05:00 UPSTREAM: : Added validation to check if OKD featureset is being enabled on OKD clusters
- - 8504fe0c7 2026-01-13T14:38:55-05:00 UPSTREAM: : Vendored API repo
-
-- oc image-arm64 430c82293109e23f3caaf9ba60e5affd2d5356f5 to 7e80dbab5a9ce563cd4f78f2874f18e4664767f5
- - 08d5f27a 2026-01-30T14:17:04+01:00 expose: Fix labels not being added to route
- - e87384f5 2026-01-29T20:38:10-05:00 Revert "CNTRLPLANE-2656:Migrating oc cli tests to ote"
- - 9619e215 2026-01-28T11:01:38-05:00 OSDOCS#18071: Updating CLI docs templates to include a required abstract/short description
- - 63b9258c 2026-01-28T19:41:37+05:30 removing bindata.go
- - c423f7b7 2026-01-21T12:39:18+05:30 Removed sos cases
-
-- kubernetes image-arm64 0a955ccf26bb6091b9053309eb0ce0b2992fed70 to 9d521311f5fb67dc43f49eeb728ee2c80976835a
- - bb37a6c1a 2026-02-03T09:47:51+01:00 UPSTREAM: 136202: raise kubelet CSI init backoff to cover ~140s DNS delays
-
diff --git a/scripts/auto-rebase/commits.txt b/scripts/auto-rebase/commits.txt
index e594e8cae6..4ed5fd8759 100644
--- a/scripts/auto-rebase/commits.txt
+++ b/scripts/auto-rebase/commits.txt
@@ -1,35 +1,35 @@
-https://github.com/openshift/api embedded-component 81371d13d1fcad175a48627cf11524a94a80c377
+https://github.com/openshift/api embedded-component d34f11c515b3d00fdb3809cd59737e3bd77167c4
https://github.com/openshift/cluster-csi-snapshot-controller-operator embedded-component 7b6335396677dfd392dc72e1f1bbb5afcfa74a44
-https://github.com/openshift/cluster-dns-operator embedded-component 41a53fed36e6e99c7c9ceb3a699c3547ee5d9bb9
-https://github.com/openshift/cluster-ingress-operator embedded-component 77901360f18951f2a51d38acd1a07714f9183493
-https://github.com/openshift/cluster-kube-apiserver-operator embedded-component fecf00cbeaf1fc18178bffddab767ee8f3d7e36f
+https://github.com/openshift/cluster-dns-operator embedded-component 5d7c973968909d4155796363222f6edc001e19a3
+https://github.com/openshift/cluster-ingress-operator embedded-component abfb6fa7b9c95dc54fb3988e84297912ad88e0e4
+https://github.com/openshift/cluster-kube-apiserver-operator embedded-component cee7acb6c820b707fbb1e1dc01cef6c1971f146d
https://github.com/openshift/cluster-kube-controller-manager-operator embedded-component a6a751080c9b2bdd3a721851b206cf2f7c8bbc41
-https://github.com/openshift/cluster-kube-scheduler-operator embedded-component b37b73a87e7a6612f3354c2ffc134a23a0a8c13c
-https://github.com/openshift/cluster-network-operator embedded-component f0bdee37451757734c3e84cb6c0a8646290c4ffa
-https://github.com/openshift/cluster-openshift-controller-manager-operator embedded-component a6ce1136e71ded4af3cb5e771435e098b5e30349
+https://github.com/openshift/cluster-kube-scheduler-operator embedded-component 14c5fdcfc2602292e19cab8713e42accf94b593d
+https://github.com/openshift/cluster-network-operator embedded-component 9d540eb7929f83879d3dafbcd1ae6cb1feca36b3
+https://github.com/openshift/cluster-openshift-controller-manager-operator embedded-component 7634c413830a510ff942bd6886ffe5f79db707b4
https://github.com/openshift/cluster-policy-controller embedded-component 8b775487512fb543bff470ff1042bd3ac31b29be
https://github.com/openshift/csi-external-snapshotter embedded-component d20b90a92cd7d77166319f5bc2feb80623747d28
https://github.com/openshift/etcd embedded-component 6a0992267004177e385e35b91e186635a644dbfe
-https://github.com/openshift/kubernetes embedded-component 9d521311f5fb67dc43f49eeb728ee2c80976835a
+https://github.com/openshift/kubernetes embedded-component 047d96223dd843e9d54bed59bc212d2e9122c56a
https://github.com/openshift/kubernetes-kube-storage-version-migrator embedded-component 73b468abf83d3d5894534f5d5cc42d1cad2a9045
-https://github.com/openshift/machine-config-operator embedded-component 067395ed863e0254c4e7ce85bf8bce7e464778bb
+https://github.com/openshift/machine-config-operator embedded-component 7eb4793ae255b19327e781f66aaf1dbd3e5210c5
https://github.com/openshift/openshift-controller-manager embedded-component 19ac71374ea7d42957fe0eb3cc6d38679cc257e1
-https://github.com/openshift/operator-framework-olm embedded-component fae41b2724eeab7a0e9b1ad89408bbbb36516fe2
-https://github.com/openshift/route-controller-manager embedded-component 2b9e93a5f0fc1e93090bbe34ce95f3b4ad5cff15
+https://github.com/openshift/operator-framework-olm embedded-component 811919f88bc3b8da4f97c6e6ca031258cc4fa13b
+https://github.com/openshift/route-controller-manager embedded-component 624742d93f3a7885cf7f70985f1e23ff60da580d
https://github.com/openshift/service-ca-operator embedded-component 503e4f5f4c74fd095a8dca385541125f3c9ee28b
-https://github.com/openshift/oc image-amd64 7e80dbab5a9ce563cd4f78f2874f18e4664767f5
+https://github.com/openshift/oc image-amd64 8b0a043216f7ae608606afb5bdb0ce451561021e
https://github.com/openshift/coredns image-amd64 9798af8539c27ad02bd376006cd3a9a7b23e5966
https://github.com/openshift/csi-external-snapshotter image-amd64 d20b90a92cd7d77166319f5bc2feb80623747d28
-https://github.com/openshift/router image-amd64 d2db065ae452ecfdb482f0ac4c6778b0c0e48b7f
+https://github.com/openshift/router image-amd64 d8ed3559fd4808a4f10c927ba4a199d3fd5b84a2
https://github.com/openshift/kube-rbac-proxy image-amd64 c7ab76fd6fdf651d5022db8946c35b158ecc2396
-https://github.com/openshift/ovn-kubernetes image-amd64 1938041fd8f8c1fb5d376fa59faec1fef7614a92
-https://github.com/openshift/kubernetes image-amd64 9d521311f5fb67dc43f49eeb728ee2c80976835a
+https://github.com/openshift/ovn-kubernetes image-amd64 2a9cd189db9c74dc678fcfca68473d6fdc278028
+https://github.com/openshift/kubernetes image-amd64 047d96223dd843e9d54bed59bc212d2e9122c56a
https://github.com/openshift/service-ca-operator image-amd64 503e4f5f4c74fd095a8dca385541125f3c9ee28b
-https://github.com/openshift/oc image-arm64 7e80dbab5a9ce563cd4f78f2874f18e4664767f5
+https://github.com/openshift/oc image-arm64 7f88fe2132f6969e1686808e5301aa3c808d4a45
https://github.com/openshift/coredns image-arm64 9798af8539c27ad02bd376006cd3a9a7b23e5966
https://github.com/openshift/csi-external-snapshotter image-arm64 d20b90a92cd7d77166319f5bc2feb80623747d28
-https://github.com/openshift/router image-arm64 d2db065ae452ecfdb482f0ac4c6778b0c0e48b7f
+https://github.com/openshift/router image-arm64 d8ed3559fd4808a4f10c927ba4a199d3fd5b84a2
https://github.com/openshift/kube-rbac-proxy image-arm64 c7ab76fd6fdf651d5022db8946c35b158ecc2396
-https://github.com/openshift/ovn-kubernetes image-arm64 1938041fd8f8c1fb5d376fa59faec1fef7614a92
-https://github.com/openshift/kubernetes image-arm64 9d521311f5fb67dc43f49eeb728ee2c80976835a
+https://github.com/openshift/ovn-kubernetes image-arm64 2a9cd189db9c74dc678fcfca68473d6fdc278028
+https://github.com/openshift/kubernetes image-arm64 047d96223dd843e9d54bed59bc212d2e9122c56a
https://github.com/openshift/service-ca-operator image-arm64 503e4f5f4c74fd095a8dca385541125f3c9ee28b
diff --git a/scripts/auto-rebase/last_rebase.sh b/scripts/auto-rebase/last_rebase.sh
index b0eb8ea4db..ec245165ac 100755
--- a/scripts/auto-rebase/last_rebase.sh
+++ b/scripts/auto-rebase/last_rebase.sh
@@ -1,2 +1,2 @@
#!/bin/bash -x
-./scripts/auto-rebase/rebase.sh to "registry.ci.openshift.org/ocp/release:4.22.0-0.nightly-2026-02-05-115400" "registry.ci.openshift.org/ocp-arm64/release-arm64:4.22.0-0.nightly-arm64-2026-02-05-082424"
+./scripts/auto-rebase/rebase.sh to "registry.ci.openshift.org/ocp/release:4.22.0-0.nightly-2026-02-17-112443" "registry.ci.openshift.org/ocp-arm64/release-arm64:4.22.0-0.nightly-arm64-2026-02-17-232712"
diff --git a/scripts/fetch_tools.sh b/scripts/fetch_tools.sh
index f451762fb3..4d39f4b308 100755
--- a/scripts/fetch_tools.sh
+++ b/scripts/fetch_tools.sh
@@ -54,10 +54,10 @@ _install() {
}
gettool_golangci-lint() {
- local ver="2.1.6"
+ local ver="2.10.1"
declare -A checksums=(
- ["x86_64"]="e55e0eb515936c0fbd178bce504798a9bd2f0b191e5e357768b18fd5415ee541"
- ["aarch64"]="582eb73880f4408d7fb89f12b502d577bd7b0b63d8c681da92bb6b9d934d4363")
+ ["x86_64"]="dfa775874cf0561b404a02a8f4481fc69b28091da95aa697259820d429b09c99"
+ ["aarch64"]="6652b42ae02915eb2f9cb2a2e0cac99514c8eded8388d88ae3e06e1a52c00de8")
declare -A arch_map=(
["x86_64"]="amd64"
diff --git a/vendor/cyphar.com/go-pathrs/.golangci.yml b/vendor/cyphar.com/go-pathrs/.golangci.yml
new file mode 100644
index 0000000000..2778a3268e
--- /dev/null
+++ b/vendor/cyphar.com/go-pathrs/.golangci.yml
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: MPL-2.0
+#
+# libpathrs: safe path resolution on Linux
+# Copyright (C) 2019-2025 Aleksa Sarai
+# Copyright (C) 2019-2025 SUSE LLC
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+version: "2"
+linters:
+ enable:
+ - bidichk
+ - cyclop
+ - errname
+ - errorlint
+ - exhaustive
+ - goconst
+ - godot
+ - gomoddirectives
+ - gosec
+ - mirror
+ - misspell
+ - mnd
+ - nilerr
+ - nilnil
+ - perfsprint
+ - prealloc
+ - reassign
+ - revive
+ - unconvert
+ - unparam
+ - usestdlibvars
+ - wastedassign
+formatters:
+ enable:
+ - gofumpt
+ - goimports
+ settings:
+ goimports:
+ local-prefixes:
+ - cyphar.com/go-pathrs
diff --git a/vendor/cyphar.com/go-pathrs/COPYING b/vendor/cyphar.com/go-pathrs/COPYING
new file mode 100644
index 0000000000..d0a1fa1482
--- /dev/null
+++ b/vendor/cyphar.com/go-pathrs/COPYING
@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+ means each individual or legal entity that creates, contributes to
+ the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+ means the combination of the Contributions of others (if any) used
+ by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+ means Source Code Form to which the initial Contributor has attached
+ the notice in Exhibit A, the Executable Form of such Source Code
+ Form, and Modifications of such Source Code Form, in each case
+ including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ (a) that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
+
+ (b) that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the
+ terms of a Secondary License.
+
+1.6. "Executable Form"
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+ means a work that combines Covered Software with other material, in
+ a separate file or files, that is not Covered Software.
+
+1.8. "License"
+ means this document.
+
+1.9. "Licensable"
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently, any and
+ all of the rights conveyed by this License.
+
+1.10. "Modifications"
+ means any of the following:
+
+ (a) any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered
+ Software; or
+
+ (b) any new file in Source Code Form that contains any Covered
+ Software.
+
+1.11. "Patent Claims" of a Contributor
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the
+ License, by the making, using, selling, offering for sale, having
+ made, import, or transfer of either its Contributions or its
+ Contributor Version.
+
+1.12. "Secondary License"
+ means either the GNU General Public License, Version 2.0, the GNU
+ Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those
+ licenses.
+
+1.13. "Source Code Form"
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+ for sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+ or
+
+(b) for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more
+ than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+* *
+* 6. Disclaimer of Warranty *
+* ------------------------- *
+* *
+* Covered Software is provided under this License on an "as is" *
+* basis, without warranty of any kind, either expressed, implied, or *
+* statutory, including, without limitation, warranties that the *
+* Covered Software is free of defects, merchantable, fit for a *
+* particular purpose or non-infringing. The entire risk as to the *
+* quality and performance of the Covered Software is with You. *
+* Should any Covered Software prove defective in any respect, You *
+* (not any Contributor) assume the cost of any necessary servicing, *
+* repair, or correction. This disclaimer of warranty constitutes an *
+* essential part of this License. No use of any Covered Software is *
+* authorized under this License except under this disclaimer. *
+* *
+************************************************************************
+
+************************************************************************
+* *
+* 7. Limitation of Liability *
+* -------------------------- *
+* *
+* Under no circumstances and under no legal theory, whether tort *
+* (including negligence), contract, or otherwise, shall any *
+* Contributor, or anyone who distributes Covered Software as *
+* permitted above, be liable to You for any direct, indirect, *
+* special, incidental, or consequential damages of any character *
+* including, without limitation, damages for lost profits, loss of *
+* goodwill, work stoppage, computer failure or malfunction, or any *
+* and all other commercial damages or losses, even if such party *
+* shall have been informed of the possibility of such damages. This *
+* limitation of liability shall not apply to liability for death or *
+* personal injury resulting from such party's negligence to the *
+* extent applicable law prohibits such limitation. Some *
+* jurisdictions do not allow the exclusion or limitation of *
+* incidental or consequential damages, so this exclusion and *
+* limitation may not apply to You. *
+* *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+ This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
diff --git a/vendor/cyphar.com/go-pathrs/doc.go b/vendor/cyphar.com/go-pathrs/doc.go
new file mode 100644
index 0000000000..a7ee4bc487
--- /dev/null
+++ b/vendor/cyphar.com/go-pathrs/doc.go
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: MPL-2.0
+/*
+ * libpathrs: safe path resolution on Linux
+ * Copyright (C) 2019-2025 Aleksa Sarai
+ * Copyright (C) 2019-2025 SUSE LLC
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+// Package pathrs provides bindings for libpathrs, a library for safe path
+// resolution on Linux.
+package pathrs
diff --git a/vendor/cyphar.com/go-pathrs/handle_linux.go b/vendor/cyphar.com/go-pathrs/handle_linux.go
new file mode 100644
index 0000000000..3221ef6738
--- /dev/null
+++ b/vendor/cyphar.com/go-pathrs/handle_linux.go
@@ -0,0 +1,114 @@
+//go:build linux
+
+// SPDX-License-Identifier: MPL-2.0
+/*
+ * libpathrs: safe path resolution on Linux
+ * Copyright (C) 2019-2025 Aleksa Sarai
+ * Copyright (C) 2019-2025 SUSE LLC
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package pathrs
+
+import (
+ "fmt"
+ "os"
+
+ "cyphar.com/go-pathrs/internal/fdutils"
+ "cyphar.com/go-pathrs/internal/libpathrs"
+)
+
+// Handle is a handle for a path within a given [Root]. This handle references
+// an already-resolved path which can be used for only one purpose -- to
+// "re-open" the handle and get an actual [os.File] which can be used for
+// ordinary operations.
+//
+// If you wish to open a file without having an intermediate [Handle] object,
+// you can try to use [Root.Open] or [Root.OpenFile].
+//
+// It is critical that perform all relevant operations through this [Handle]
+// (rather than fetching the file descriptor yourself with [Handle.IntoRaw]),
+// because the security properties of libpathrs depend on users doing all
+// relevant filesystem operations through libpathrs.
+//
+// [os.File]: https://pkg.go.dev/os#File
+type Handle struct {
+ inner *os.File
+}
+
+// HandleFromFile creates a new [Handle] from an existing file handle. The
+// handle will be copied by this method, so the original handle should still be
+// freed by the caller.
+//
+// This is effectively the inverse operation of [Handle.IntoRaw], and is used
+// for "deserialising" pathrs root handles.
+func HandleFromFile(file *os.File) (*Handle, error) {
+ newFile, err := fdutils.DupFile(file)
+ if err != nil {
+ return nil, fmt.Errorf("duplicate handle fd: %w", err)
+ }
+ return &Handle{inner: newFile}, nil
+}
+
+// Open creates an "upgraded" file handle to the file referenced by the
+// [Handle]. Note that the original [Handle] is not consumed by this operation,
+// and can be opened multiple times.
+//
+// The handle returned is only usable for reading, and this is method is
+// shorthand for [Handle.OpenFile] with os.O_RDONLY.
+//
+// TODO: Rename these to "Reopen" or something.
+func (h *Handle) Open() (*os.File, error) {
+ return h.OpenFile(os.O_RDONLY)
+}
+
+// OpenFile creates an "upgraded" file handle to the file referenced by the
+// [Handle]. Note that the original [Handle] is not consumed by this operation,
+// and can be opened multiple times.
+//
+// The provided flags indicate which open(2) flags are used to create the new
+// handle.
+//
+// TODO: Rename these to "Reopen" or something.
+func (h *Handle) OpenFile(flags int) (*os.File, error) {
+ return fdutils.WithFileFd(h.inner, func(fd uintptr) (*os.File, error) {
+ newFd, err := libpathrs.Reopen(fd, flags)
+ if err != nil {
+ return nil, err
+ }
+ return os.NewFile(newFd, h.inner.Name()), nil
+ })
+}
+
+// IntoFile unwraps the [Handle] into its underlying [os.File].
+//
+// You almost certainly want to use [Handle.OpenFile] to get a non-O_PATH
+// version of this [Handle].
+//
+// This operation returns the internal [os.File] of the [Handle] directly, so
+// calling [Handle.Close] will also close any copies of the returned [os.File].
+// If you want to get an independent copy, use [Handle.Clone] followed by
+// [Handle.IntoFile] on the cloned [Handle].
+//
+// [os.File]: https://pkg.go.dev/os#File
+func (h *Handle) IntoFile() *os.File {
+ // TODO: Figure out if we really don't want to make a copy.
+ // TODO: We almost certainly want to clear r.inner here, but we can't do
+ // that easily atomically (we could use atomic.Value but that'll make
+ // things quite a bit uglier).
+ return h.inner
+}
+
+// Clone creates a copy of a [Handle], such that it has a separate lifetime to
+// the original (while referring to the same underlying file).
+func (h *Handle) Clone() (*Handle, error) {
+ return HandleFromFile(h.inner)
+}
+
+// Close frees all of the resources used by the [Handle].
+func (h *Handle) Close() error {
+ return h.inner.Close()
+}
diff --git a/vendor/cyphar.com/go-pathrs/internal/fdutils/fd_linux.go b/vendor/cyphar.com/go-pathrs/internal/fdutils/fd_linux.go
new file mode 100644
index 0000000000..41aea3e4b3
--- /dev/null
+++ b/vendor/cyphar.com/go-pathrs/internal/fdutils/fd_linux.go
@@ -0,0 +1,75 @@
+//go:build linux
+
+// SPDX-License-Identifier: MPL-2.0
+/*
+ * libpathrs: safe path resolution on Linux
+ * Copyright (C) 2019-2025 Aleksa Sarai
+ * Copyright (C) 2019-2025 SUSE LLC
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+// Package fdutils contains a few helper methods when dealing with *os.File and
+// file descriptors.
+package fdutils
+
+import (
+ "fmt"
+ "os"
+
+ "golang.org/x/sys/unix"
+
+ "cyphar.com/go-pathrs/internal/libpathrs"
+)
+
+// DupFd makes a duplicate of the given fd.
+func DupFd(fd uintptr, name string) (*os.File, error) {
+ newFd, err := unix.FcntlInt(fd, unix.F_DUPFD_CLOEXEC, 0)
+ if err != nil {
+ return nil, fmt.Errorf("fcntl(F_DUPFD_CLOEXEC): %w", err)
+ }
+ return os.NewFile(uintptr(newFd), name), nil
+}
+
+// WithFileFd is a more ergonomic wrapper around file.SyscallConn().Control().
+func WithFileFd[T any](file *os.File, fn func(fd uintptr) (T, error)) (T, error) {
+ conn, err := file.SyscallConn()
+ if err != nil {
+ return *new(T), err
+ }
+ var (
+ ret T
+ innerErr error
+ )
+ if err := conn.Control(func(fd uintptr) {
+ ret, innerErr = fn(fd)
+ }); err != nil {
+ return *new(T), err
+ }
+ return ret, innerErr
+}
+
+// DupFile makes a duplicate of the given file.
+func DupFile(file *os.File) (*os.File, error) {
+ return WithFileFd(file, func(fd uintptr) (*os.File, error) {
+ return DupFd(fd, file.Name())
+ })
+}
+
+// MkFile creates a new *os.File from the provided file descriptor. However,
+// unlike os.NewFile, the file's Name is based on the real path (provided by
+// /proc/self/fd/$n).
+func MkFile(fd uintptr) (*os.File, error) {
+ fdPath := fmt.Sprintf("fd/%d", fd)
+ fdName, err := libpathrs.ProcReadlinkat(libpathrs.ProcDefaultRootFd, libpathrs.ProcThreadSelf, fdPath)
+ if err != nil {
+ _ = unix.Close(int(fd))
+ return nil, fmt.Errorf("failed to fetch real name of fd %d: %w", fd, err)
+ }
+ // TODO: Maybe we should prefix this name with something to indicate to
+ // users that they must not use this path as a "safe" path. Something like
+ // "//pathrs-handle:/foo/bar"?
+ return os.NewFile(fd, fdName), nil
+}
diff --git a/vendor/cyphar.com/go-pathrs/internal/libpathrs/error_unix.go b/vendor/cyphar.com/go-pathrs/internal/libpathrs/error_unix.go
new file mode 100644
index 0000000000..c9f416de01
--- /dev/null
+++ b/vendor/cyphar.com/go-pathrs/internal/libpathrs/error_unix.go
@@ -0,0 +1,40 @@
+//go:build linux
+
+// TODO: Use "go:build unix" once we bump the minimum Go version 1.19.
+
+// SPDX-License-Identifier: MPL-2.0
+/*
+ * libpathrs: safe path resolution on Linux
+ * Copyright (C) 2019-2025 Aleksa Sarai
+ * Copyright (C) 2019-2025 SUSE LLC
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package libpathrs
+
+import (
+ "syscall"
+)
+
+// Error represents an underlying libpathrs error.
+type Error struct {
+ description string
+ errno syscall.Errno
+}
+
+// Error returns a textual description of the error.
+func (err *Error) Error() string {
+ return err.description
+}
+
+// Unwrap returns the underlying error which was wrapped by this error (if
+// applicable).
+func (err *Error) Unwrap() error {
+ if err.errno != 0 {
+ return err.errno
+ }
+ return nil
+}
diff --git a/vendor/cyphar.com/go-pathrs/internal/libpathrs/libpathrs_linux.go b/vendor/cyphar.com/go-pathrs/internal/libpathrs/libpathrs_linux.go
new file mode 100644
index 0000000000..c07b80e307
--- /dev/null
+++ b/vendor/cyphar.com/go-pathrs/internal/libpathrs/libpathrs_linux.go
@@ -0,0 +1,337 @@
+//go:build linux
+
+// SPDX-License-Identifier: MPL-2.0
+/*
+ * libpathrs: safe path resolution on Linux
+ * Copyright (C) 2019-2025 Aleksa Sarai
+ * Copyright (C) 2019-2025 SUSE LLC
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+// Package libpathrs is an internal thin wrapper around the libpathrs C API.
+package libpathrs
+
+import (
+ "fmt"
+ "syscall"
+ "unsafe"
+)
+
+/*
+// TODO: Figure out if we need to add support for linking against libpathrs
+// statically even if in dynamically linked builds in order to make
+// packaging a bit easier (using "-Wl,-Bstatic -lpathrs -Wl,-Bdynamic" or
+// "-l:pathrs.a").
+#cgo pkg-config: pathrs
+#include
+
+// This is a workaround for unsafe.Pointer() not working for non-void pointers.
+char *cast_ptr(void *ptr) { return ptr; }
+*/
+import "C"
+
+func fetchError(errID C.int) error {
+ if errID >= C.__PATHRS_MAX_ERR_VALUE {
+ return nil
+ }
+ cErr := C.pathrs_errorinfo(errID)
+ defer C.pathrs_errorinfo_free(cErr)
+
+ var err error
+ if cErr != nil {
+ err = &Error{
+ errno: syscall.Errno(cErr.saved_errno),
+ description: C.GoString(cErr.description),
+ }
+ }
+ return err
+}
+
+// OpenRoot wraps pathrs_open_root.
+func OpenRoot(path string) (uintptr, error) {
+ cPath := C.CString(path)
+ defer C.free(unsafe.Pointer(cPath))
+
+ fd := C.pathrs_open_root(cPath)
+ return uintptr(fd), fetchError(fd)
+}
+
+// Reopen wraps pathrs_reopen.
+func Reopen(fd uintptr, flags int) (uintptr, error) {
+ newFd := C.pathrs_reopen(C.int(fd), C.int(flags))
+ return uintptr(newFd), fetchError(newFd)
+}
+
+// InRootResolve wraps pathrs_inroot_resolve.
+func InRootResolve(rootFd uintptr, path string) (uintptr, error) {
+ cPath := C.CString(path)
+ defer C.free(unsafe.Pointer(cPath))
+
+ fd := C.pathrs_inroot_resolve(C.int(rootFd), cPath)
+ return uintptr(fd), fetchError(fd)
+}
+
+// InRootResolveNoFollow wraps pathrs_inroot_resolve_nofollow.
+func InRootResolveNoFollow(rootFd uintptr, path string) (uintptr, error) {
+ cPath := C.CString(path)
+ defer C.free(unsafe.Pointer(cPath))
+
+ fd := C.pathrs_inroot_resolve_nofollow(C.int(rootFd), cPath)
+ return uintptr(fd), fetchError(fd)
+}
+
+// InRootOpen wraps pathrs_inroot_open.
+func InRootOpen(rootFd uintptr, path string, flags int) (uintptr, error) {
+ cPath := C.CString(path)
+ defer C.free(unsafe.Pointer(cPath))
+
+ fd := C.pathrs_inroot_open(C.int(rootFd), cPath, C.int(flags))
+ return uintptr(fd), fetchError(fd)
+}
+
+// InRootReadlink wraps pathrs_inroot_readlink.
+func InRootReadlink(rootFd uintptr, path string) (string, error) {
+ cPath := C.CString(path)
+ defer C.free(unsafe.Pointer(cPath))
+
+ size := 128
+ for {
+ linkBuf := make([]byte, size)
+ n := C.pathrs_inroot_readlink(C.int(rootFd), cPath, C.cast_ptr(unsafe.Pointer(&linkBuf[0])), C.ulong(len(linkBuf)))
+ switch {
+ case int(n) < C.__PATHRS_MAX_ERR_VALUE:
+ return "", fetchError(n)
+ case int(n) <= len(linkBuf):
+ return string(linkBuf[:int(n)]), nil
+ default:
+ // The contents were truncated. Unlike readlinkat, pathrs returns
+ // the size of the link when it checked. So use the returned size
+ // as a basis for the reallocated size (but in order to avoid a DoS
+ // where a magic-link is growing by a single byte each iteration,
+ // make sure we are a fair bit larger).
+ size += int(n)
+ }
+ }
+}
+
+// InRootRmdir wraps pathrs_inroot_rmdir.
+func InRootRmdir(rootFd uintptr, path string) error {
+ cPath := C.CString(path)
+ defer C.free(unsafe.Pointer(cPath))
+
+ err := C.pathrs_inroot_rmdir(C.int(rootFd), cPath)
+ return fetchError(err)
+}
+
+// InRootUnlink wraps pathrs_inroot_unlink.
+func InRootUnlink(rootFd uintptr, path string) error {
+ cPath := C.CString(path)
+ defer C.free(unsafe.Pointer(cPath))
+
+ err := C.pathrs_inroot_unlink(C.int(rootFd), cPath)
+ return fetchError(err)
+}
+
+// InRootRemoveAll wraps pathrs_inroot_remove_all.
+func InRootRemoveAll(rootFd uintptr, path string) error {
+ cPath := C.CString(path)
+ defer C.free(unsafe.Pointer(cPath))
+
+ err := C.pathrs_inroot_remove_all(C.int(rootFd), cPath)
+ return fetchError(err)
+}
+
+// InRootCreat wraps pathrs_inroot_creat.
+func InRootCreat(rootFd uintptr, path string, flags int, mode uint32) (uintptr, error) {
+ cPath := C.CString(path)
+ defer C.free(unsafe.Pointer(cPath))
+
+ fd := C.pathrs_inroot_creat(C.int(rootFd), cPath, C.int(flags), C.uint(mode))
+ return uintptr(fd), fetchError(fd)
+}
+
+// InRootRename wraps pathrs_inroot_rename.
+func InRootRename(rootFd uintptr, src, dst string, flags uint) error {
+ cSrc := C.CString(src)
+ defer C.free(unsafe.Pointer(cSrc))
+
+ cDst := C.CString(dst)
+ defer C.free(unsafe.Pointer(cDst))
+
+ err := C.pathrs_inroot_rename(C.int(rootFd), cSrc, cDst, C.uint(flags))
+ return fetchError(err)
+}
+
+// InRootMkdir wraps pathrs_inroot_mkdir.
+func InRootMkdir(rootFd uintptr, path string, mode uint32) error {
+ cPath := C.CString(path)
+ defer C.free(unsafe.Pointer(cPath))
+
+ err := C.pathrs_inroot_mkdir(C.int(rootFd), cPath, C.uint(mode))
+ return fetchError(err)
+}
+
+// InRootMkdirAll wraps pathrs_inroot_mkdir_all.
+func InRootMkdirAll(rootFd uintptr, path string, mode uint32) (uintptr, error) {
+ cPath := C.CString(path)
+ defer C.free(unsafe.Pointer(cPath))
+
+ fd := C.pathrs_inroot_mkdir_all(C.int(rootFd), cPath, C.uint(mode))
+ return uintptr(fd), fetchError(fd)
+}
+
+// InRootMknod wraps pathrs_inroot_mknod.
+func InRootMknod(rootFd uintptr, path string, mode uint32, dev uint64) error {
+ cPath := C.CString(path)
+ defer C.free(unsafe.Pointer(cPath))
+
+ err := C.pathrs_inroot_mknod(C.int(rootFd), cPath, C.uint(mode), C.dev_t(dev))
+ return fetchError(err)
+}
+
+// InRootSymlink wraps pathrs_inroot_symlink.
+func InRootSymlink(rootFd uintptr, path, target string) error {
+ cPath := C.CString(path)
+ defer C.free(unsafe.Pointer(cPath))
+
+ cTarget := C.CString(target)
+ defer C.free(unsafe.Pointer(cTarget))
+
+ err := C.pathrs_inroot_symlink(C.int(rootFd), cPath, cTarget)
+ return fetchError(err)
+}
+
+// InRootHardlink wraps pathrs_inroot_hardlink.
+func InRootHardlink(rootFd uintptr, path, target string) error {
+ cPath := C.CString(path)
+ defer C.free(unsafe.Pointer(cPath))
+
+ cTarget := C.CString(target)
+ defer C.free(unsafe.Pointer(cTarget))
+
+ err := C.pathrs_inroot_hardlink(C.int(rootFd), cPath, cTarget)
+ return fetchError(err)
+}
+
+// ProcBase is pathrs_proc_base_t (uint64_t).
+type ProcBase C.pathrs_proc_base_t
+
+// FIXME: We need to open-code the constants because CGo unfortunately will
+// implicitly convert any non-literal constants (i.e. those resolved using gcc)
+// to signed integers. See for some
+// more information on the underlying issue (though.
+const (
+ // ProcRoot is PATHRS_PROC_ROOT.
+ ProcRoot ProcBase = 0xFFFF_FFFE_7072_6F63 // C.PATHRS_PROC_ROOT
+ // ProcSelf is PATHRS_PROC_SELF.
+ ProcSelf ProcBase = 0xFFFF_FFFE_091D_5E1F // C.PATHRS_PROC_SELF
+ // ProcThreadSelf is PATHRS_PROC_THREAD_SELF.
+ ProcThreadSelf ProcBase = 0xFFFF_FFFE_3EAD_5E1F // C.PATHRS_PROC_THREAD_SELF
+
+ // ProcBaseTypeMask is __PATHRS_PROC_TYPE_MASK.
+ ProcBaseTypeMask ProcBase = 0xFFFF_FFFF_0000_0000 // C.__PATHRS_PROC_TYPE_MASK
+ // ProcBaseTypePid is __PATHRS_PROC_TYPE_PID.
+ ProcBaseTypePid ProcBase = 0x8000_0000_0000_0000 // C.__PATHRS_PROC_TYPE_PID
+
+ // ProcDefaultRootFd is PATHRS_PROC_DEFAULT_ROOTFD.
+ ProcDefaultRootFd = -int(syscall.EBADF) // C.PATHRS_PROC_DEFAULT_ROOTFD
+)
+
+func assertEqual[T comparable](a, b T, msg string) {
+ if a != b {
+ panic(fmt.Sprintf("%s ((%T) %#v != (%T) %#v)", msg, a, a, b, b))
+ }
+}
+
+// Verify that the values above match the actual C values. Unfortunately, Go
+// only allows us to forcefully cast int64 to uint64 if you use a temporary
+// variable, which means we cannot do it in a const context and thus need to do
+// it at runtime (even though it is a check that fundamentally could be done at
+// compile-time)...
+func init() {
+ var (
+ actualProcRoot int64 = C.PATHRS_PROC_ROOT
+ actualProcSelf int64 = C.PATHRS_PROC_SELF
+ actualProcThreadSelf int64 = C.PATHRS_PROC_THREAD_SELF
+ )
+
+ assertEqual(ProcRoot, ProcBase(actualProcRoot), "PATHRS_PROC_ROOT")
+ assertEqual(ProcSelf, ProcBase(actualProcSelf), "PATHRS_PROC_SELF")
+ assertEqual(ProcThreadSelf, ProcBase(actualProcThreadSelf), "PATHRS_PROC_THREAD_SELF")
+
+ var (
+ actualProcBaseTypeMask uint64 = C.__PATHRS_PROC_TYPE_MASK
+ actualProcBaseTypePid uint64 = C.__PATHRS_PROC_TYPE_PID
+ )
+
+ assertEqual(ProcBaseTypeMask, ProcBase(actualProcBaseTypeMask), "__PATHRS_PROC_TYPE_MASK")
+ assertEqual(ProcBaseTypePid, ProcBase(actualProcBaseTypePid), "__PATHRS_PROC_TYPE_PID")
+
+ assertEqual(ProcDefaultRootFd, int(C.PATHRS_PROC_DEFAULT_ROOTFD), "PATHRS_PROC_DEFAULT_ROOTFD")
+}
+
+// ProcPid reimplements the PROC_PID(x) conversion.
+func ProcPid(pid uint32) ProcBase { return ProcBaseTypePid | ProcBase(pid) }
+
+// ProcOpenat wraps pathrs_proc_openat.
+func ProcOpenat(procRootFd int, base ProcBase, path string, flags int) (uintptr, error) {
+ cBase := C.pathrs_proc_base_t(base)
+
+ cPath := C.CString(path)
+ defer C.free(unsafe.Pointer(cPath))
+
+ fd := C.pathrs_proc_openat(C.int(procRootFd), cBase, cPath, C.int(flags))
+ return uintptr(fd), fetchError(fd)
+}
+
+// ProcReadlinkat wraps pathrs_proc_readlinkat.
+func ProcReadlinkat(procRootFd int, base ProcBase, path string) (string, error) {
+ // TODO: See if we can unify this code with InRootReadlink.
+
+ cBase := C.pathrs_proc_base_t(base)
+
+ cPath := C.CString(path)
+ defer C.free(unsafe.Pointer(cPath))
+
+ size := 128
+ for {
+ linkBuf := make([]byte, size)
+ n := C.pathrs_proc_readlinkat(
+ C.int(procRootFd), cBase, cPath,
+ C.cast_ptr(unsafe.Pointer(&linkBuf[0])), C.ulong(len(linkBuf)))
+ switch {
+ case int(n) < C.__PATHRS_MAX_ERR_VALUE:
+ return "", fetchError(n)
+ case int(n) <= len(linkBuf):
+ return string(linkBuf[:int(n)]), nil
+ default:
+ // The contents were truncated. Unlike readlinkat, pathrs returns
+ // the size of the link when it checked. So use the returned size
+ // as a basis for the reallocated size (but in order to avoid a DoS
+ // where a magic-link is growing by a single byte each iteration,
+ // make sure we are a fair bit larger).
+ size += int(n)
+ }
+ }
+}
+
+// ProcfsOpenHow is pathrs_procfs_open_how (struct).
+type ProcfsOpenHow C.pathrs_procfs_open_how
+
+const (
+ // ProcfsNewUnmasked is PATHRS_PROCFS_NEW_UNMASKED.
+ ProcfsNewUnmasked = C.PATHRS_PROCFS_NEW_UNMASKED
+)
+
+// Flags returns a pointer to the internal flags field to allow other packages
+// to modify structure fields that are internal due to Go's visibility model.
+func (how *ProcfsOpenHow) Flags() *C.uint64_t { return &how.flags }
+
+// ProcfsOpen is pathrs_procfs_open (sizeof(*how) is passed automatically).
+func ProcfsOpen(how *ProcfsOpenHow) (uintptr, error) {
+ fd := C.pathrs_procfs_open((*C.pathrs_procfs_open_how)(how), C.size_t(unsafe.Sizeof(*how)))
+ return uintptr(fd), fetchError(fd)
+}
diff --git a/vendor/cyphar.com/go-pathrs/procfs/procfs_linux.go b/vendor/cyphar.com/go-pathrs/procfs/procfs_linux.go
new file mode 100644
index 0000000000..5533c427cb
--- /dev/null
+++ b/vendor/cyphar.com/go-pathrs/procfs/procfs_linux.go
@@ -0,0 +1,246 @@
+//go:build linux
+
+// SPDX-License-Identifier: MPL-2.0
+/*
+ * libpathrs: safe path resolution on Linux
+ * Copyright (C) 2019-2025 Aleksa Sarai
+ * Copyright (C) 2019-2025 SUSE LLC
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+// Package procfs provides a safe API for operating on /proc on Linux.
+package procfs
+
+import (
+ "os"
+ "runtime"
+
+ "cyphar.com/go-pathrs/internal/fdutils"
+ "cyphar.com/go-pathrs/internal/libpathrs"
+)
+
+// ProcBase is used with [ProcReadlink] and related functions to indicate what
+// /proc subpath path operations should be done relative to.
+type ProcBase struct {
+ inner libpathrs.ProcBase
+}
+
+var (
+ // ProcRoot indicates to use /proc. Note that this mode may be more
+ // expensive because we have to take steps to try to avoid leaking unmasked
+ // procfs handles, so you should use [ProcBaseSelf] if you can.
+ ProcRoot = ProcBase{inner: libpathrs.ProcRoot}
+ // ProcSelf indicates to use /proc/self. For most programs, this is the
+ // standard choice.
+ ProcSelf = ProcBase{inner: libpathrs.ProcSelf}
+ // ProcThreadSelf indicates to use /proc/thread-self. In multi-threaded
+ // programs where one thread has a different CLONE_FS, it is possible for
+ // /proc/self to point the wrong thread and so /proc/thread-self may be
+ // necessary.
+ ProcThreadSelf = ProcBase{inner: libpathrs.ProcThreadSelf}
+)
+
+// ProcPid returns a ProcBase which indicates to use /proc/$pid for the given
+// PID (or TID). Be aware that due to PID recycling, using this is generally
+// not safe except in certain circumstances. Namely:
+//
+// - PID 1 (the init process), as that PID cannot ever get recycled.
+// - Your current PID (though you should just use [ProcBaseSelf]).
+// - Your current TID if you have used [runtime.LockOSThread] (though you
+// should just use [ProcBaseThreadSelf]).
+// - PIDs of child processes (as long as you are sure that no other part of
+// your program incorrectly catches or ignores SIGCHLD, and that you do it
+// *before* you call wait(2)or any equivalent method that could reap
+// zombies).
+func ProcPid(pid int) ProcBase {
+ if pid < 0 || pid >= 1<<31 {
+ panic("invalid ProcBasePid value") // TODO: should this be an error?
+ }
+ return ProcBase{inner: libpathrs.ProcPid(uint32(pid))}
+}
+
+// ThreadCloser is a callback that needs to be called when you are done
+// operating on an [os.File] fetched using [Handle.OpenThreadSelf].
+//
+// [os.File]: https://pkg.go.dev/os#File
+type ThreadCloser func()
+
+// Handle is a wrapper around an *os.File handle to "/proc", which can be
+// used to do further procfs-related operations in a safe way.
+type Handle struct {
+ inner *os.File
+}
+
+// Close releases all internal resources for this [Handle].
+//
+// Note that if the handle is actually the global cached handle, this operation
+// is a no-op.
+func (proc *Handle) Close() error {
+ var err error
+ if proc.inner != nil {
+ err = proc.inner.Close()
+ }
+ return err
+}
+
+// OpenOption is a configuration function passed as an argument to [Open].
+type OpenOption func(*libpathrs.ProcfsOpenHow) error
+
+// UnmaskedProcRoot can be passed to [Open] to request an unmasked procfs
+// handle be created.
+//
+// procfs, err := procfs.OpenRoot(procfs.UnmaskedProcRoot)
+func UnmaskedProcRoot(how *libpathrs.ProcfsOpenHow) error {
+ *how.Flags() |= libpathrs.ProcfsNewUnmasked
+ return nil
+}
+
+// Open creates a new [Handle] to a safe "/proc", based on the passed
+// configuration options (in the form of a series of [OpenOption]s).
+func Open(opts ...OpenOption) (*Handle, error) {
+ var how libpathrs.ProcfsOpenHow
+ for _, opt := range opts {
+ if err := opt(&how); err != nil {
+ return nil, err
+ }
+ }
+ fd, err := libpathrs.ProcfsOpen(&how)
+ if err != nil {
+ return nil, err
+ }
+ var procFile *os.File
+ if int(fd) >= 0 {
+ procFile = os.NewFile(fd, "/proc")
+ }
+ // TODO: Check that fd == PATHRS_PROC_DEFAULT_ROOTFD in the <0 case?
+ return &Handle{inner: procFile}, nil
+}
+
+// TODO: Switch to something fdutils.WithFileFd-like.
+func (proc *Handle) fd() int {
+ if proc.inner != nil {
+ return int(proc.inner.Fd())
+ }
+ return libpathrs.ProcDefaultRootFd
+}
+
+// TODO: Should we expose open?
+func (proc *Handle) open(base ProcBase, path string, flags int) (_ *os.File, Closer ThreadCloser, Err error) {
+ var closer ThreadCloser
+ if base == ProcThreadSelf {
+ runtime.LockOSThread()
+ closer = runtime.UnlockOSThread
+ }
+ defer func() {
+ if closer != nil && Err != nil {
+ closer()
+ Closer = nil
+ }
+ }()
+
+ fd, err := libpathrs.ProcOpenat(proc.fd(), base.inner, path, flags)
+ if err != nil {
+ return nil, nil, err
+ }
+ file, err := fdutils.MkFile(fd)
+ return file, closer, err
+}
+
+// OpenRoot safely opens a given path from inside /proc/.
+//
+// This function must only be used for accessing global information from procfs
+// (such as /proc/cpuinfo) or information about other processes (such as
+// /proc/1). Accessing your own process information should be done using
+// [Handle.OpenSelf] or [Handle.OpenThreadSelf].
+func (proc *Handle) OpenRoot(path string, flags int) (*os.File, error) {
+ file, closer, err := proc.open(ProcRoot, path, flags)
+ if closer != nil {
+ // should not happen
+ panic("non-zero closer returned from procOpen(ProcRoot)")
+ }
+ return file, err
+}
+
+// OpenSelf safely opens a given path from inside /proc/self/.
+//
+// This method is recommend for getting process information about the current
+// process for almost all Go processes *except* for cases where there are
+// [runtime.LockOSThread] threads that have changed some aspect of their state
+// (such as through unshare(CLONE_FS) or changing namespaces).
+//
+// For such non-heterogeneous processes, /proc/self may reference to a task
+// that has different state from the current goroutine and so it may be
+// preferable to use [Handle.OpenThreadSelf]. The same is true if a user
+// really wants to inspect the current OS thread's information (such as
+// /proc/thread-self/stack or /proc/thread-self/status which is always uniquely
+// per-thread).
+//
+// Unlike [Handle.OpenThreadSelf], this method does not involve locking
+// the goroutine to the current OS thread and so is simpler to use and
+// theoretically has slightly less overhead.
+//
+// [runtime.LockOSThread]: https://pkg.go.dev/runtime#LockOSThread
+func (proc *Handle) OpenSelf(path string, flags int) (*os.File, error) {
+ file, closer, err := proc.open(ProcSelf, path, flags)
+ if closer != nil {
+ // should not happen
+ panic("non-zero closer returned from procOpen(ProcSelf)")
+ }
+ return file, err
+}
+
+// OpenPid safely opens a given path from inside /proc/$pid/, where pid can be
+// either a PID or TID.
+//
+// This is effectively equivalent to calling [Handle.OpenRoot] with the
+// pid prefixed to the subpath.
+//
+// Be aware that due to PID recycling, using this is generally not safe except
+// in certain circumstances. See the documentation of [ProcPid] for more
+// details.
+func (proc *Handle) OpenPid(pid int, path string, flags int) (*os.File, error) {
+ file, closer, err := proc.open(ProcPid(pid), path, flags)
+ if closer != nil {
+ // should not happen
+ panic("non-zero closer returned from procOpen(ProcPidOpen)")
+ }
+ return file, err
+}
+
+// OpenThreadSelf safely opens a given path from inside /proc/thread-self/.
+//
+// Most Go processes have heterogeneous threads (all threads have most of the
+// same kernel state such as CLONE_FS) and so [Handle.OpenSelf] is
+// preferable for most users.
+//
+// For non-heterogeneous threads, or users that actually want thread-specific
+// information (such as /proc/thread-self/stack or /proc/thread-self/status),
+// this method is necessary.
+//
+// Because Go can change the running OS thread of your goroutine without notice
+// (and then subsequently kill the old thread), this method will lock the
+// current goroutine to the OS thread (with [runtime.LockOSThread]) and the
+// caller is responsible for unlocking the the OS thread with the
+// [ThreadCloser] callback once they are done using the returned file. This
+// callback MUST be called AFTER you have finished using the returned
+// [os.File]. This callback is completely separate to [os.File.Close], so it
+// must be called regardless of how you close the handle.
+//
+// [runtime.LockOSThread]: https://pkg.go.dev/runtime#LockOSThread
+// [os.File]: https://pkg.go.dev/os#File
+// [os.File.Close]: https://pkg.go.dev/os#File.Close
+func (proc *Handle) OpenThreadSelf(path string, flags int) (*os.File, ThreadCloser, error) {
+ return proc.open(ProcThreadSelf, path, flags)
+}
+
+// Readlink safely reads the contents of a symlink from the given procfs base.
+//
+// This is effectively equivalent to doing an Open*(O_PATH|O_NOFOLLOW) of the
+// path and then doing unix.Readlinkat(fd, ""), but with the benefit that
+// thread locking is not necessary for [ProcThreadSelf].
+func (proc *Handle) Readlink(base ProcBase, path string) (string, error) {
+ return libpathrs.ProcReadlinkat(proc.fd(), base.inner, path)
+}
diff --git a/vendor/cyphar.com/go-pathrs/root_linux.go b/vendor/cyphar.com/go-pathrs/root_linux.go
new file mode 100644
index 0000000000..edc9e4c87f
--- /dev/null
+++ b/vendor/cyphar.com/go-pathrs/root_linux.go
@@ -0,0 +1,367 @@
+//go:build linux
+
+// SPDX-License-Identifier: MPL-2.0
+/*
+ * libpathrs: safe path resolution on Linux
+ * Copyright (C) 2019-2025 Aleksa Sarai
+ * Copyright (C) 2019-2025 SUSE LLC
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package pathrs
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "syscall"
+
+ "cyphar.com/go-pathrs/internal/fdutils"
+ "cyphar.com/go-pathrs/internal/libpathrs"
+)
+
+// Root is a handle to the root of a directory tree to resolve within. The only
+// purpose of this "root handle" is to perform operations within the directory
+// tree, or to get a [Handle] to inodes within the directory tree.
+//
+// At time of writing, it is considered a *VERY BAD IDEA* to open a [Root]
+// inside a possibly-attacker-controlled directory tree. While we do have
+// protections that should defend against it, it's far more dangerous than just
+// opening a directory tree which is not inside a potentially-untrusted
+// directory.
+type Root struct {
+ inner *os.File
+}
+
+// OpenRoot creates a new [Root] handle to the directory at the given path.
+func OpenRoot(path string) (*Root, error) {
+ fd, err := libpathrs.OpenRoot(path)
+ if err != nil {
+ return nil, err
+ }
+ file, err := fdutils.MkFile(fd)
+ if err != nil {
+ return nil, err
+ }
+ return &Root{inner: file}, nil
+}
+
+// RootFromFile creates a new [Root] handle from an [os.File] referencing a
+// directory. The provided file will be duplicated, so the original file should
+// still be closed by the caller.
+//
+// This is effectively the inverse operation of [Root.IntoFile].
+//
+// [os.File]: https://pkg.go.dev/os#File
+func RootFromFile(file *os.File) (*Root, error) {
+ newFile, err := fdutils.DupFile(file)
+ if err != nil {
+ return nil, fmt.Errorf("duplicate root fd: %w", err)
+ }
+ return &Root{inner: newFile}, nil
+}
+
+// Resolve resolves the given path within the [Root]'s directory tree, and
+// returns a [Handle] to the resolved path. The path must already exist,
+// otherwise an error will occur.
+//
+// All symlinks (including trailing symlinks) are followed, but they are
+// resolved within the rootfs. If you wish to open a handle to the symlink
+// itself, use [ResolveNoFollow].
+func (r *Root) Resolve(path string) (*Handle, error) {
+ return fdutils.WithFileFd(r.inner, func(rootFd uintptr) (*Handle, error) {
+ handleFd, err := libpathrs.InRootResolve(rootFd, path)
+ if err != nil {
+ return nil, err
+ }
+ handleFile, err := fdutils.MkFile(handleFd)
+ if err != nil {
+ return nil, err
+ }
+ return &Handle{inner: handleFile}, nil
+ })
+}
+
+// ResolveNoFollow is effectively an O_NOFOLLOW version of [Resolve]. Their
+// behaviour is identical, except that *trailing* symlinks will not be
+// followed. If the final component is a trailing symlink, an O_PATH|O_NOFOLLOW
+// handle to the symlink itself is returned.
+func (r *Root) ResolveNoFollow(path string) (*Handle, error) {
+ return fdutils.WithFileFd(r.inner, func(rootFd uintptr) (*Handle, error) {
+ handleFd, err := libpathrs.InRootResolveNoFollow(rootFd, path)
+ if err != nil {
+ return nil, err
+ }
+ handleFile, err := fdutils.MkFile(handleFd)
+ if err != nil {
+ return nil, err
+ }
+ return &Handle{inner: handleFile}, nil
+ })
+}
+
+// Open is effectively shorthand for [Resolve] followed by [Handle.Open], but
+// can be slightly more efficient (it reduces CGo overhead and the number of
+// syscalls used when using the openat2-based resolver) and is arguably more
+// ergonomic to use.
+//
+// This is effectively equivalent to [os.Open].
+//
+// [os.Open]: https://pkg.go.dev/os#Open
+func (r *Root) Open(path string) (*os.File, error) {
+ return r.OpenFile(path, os.O_RDONLY)
+}
+
+// OpenFile is effectively shorthand for [Resolve] followed by
+// [Handle.OpenFile], but can be slightly more efficient (it reduces CGo
+// overhead and the number of syscalls used when using the openat2-based
+// resolver) and is arguably more ergonomic to use.
+//
+// However, if flags contains os.O_NOFOLLOW and the path is a symlink, then
+// OpenFile's behaviour will match that of openat2. In most cases an error will
+// be returned, but if os.O_PATH is provided along with os.O_NOFOLLOW then a
+// file equivalent to [ResolveNoFollow] will be returned instead.
+//
+// This is effectively equivalent to [os.OpenFile], except that os.O_CREAT is
+// not supported.
+//
+// [os.OpenFile]: https://pkg.go.dev/os#OpenFile
+func (r *Root) OpenFile(path string, flags int) (*os.File, error) {
+ return fdutils.WithFileFd(r.inner, func(rootFd uintptr) (*os.File, error) {
+ fd, err := libpathrs.InRootOpen(rootFd, path, flags)
+ if err != nil {
+ return nil, err
+ }
+ return fdutils.MkFile(fd)
+ })
+}
+
+// Create creates a file within the [Root]'s directory tree at the given path,
+// and returns a handle to the file. The provided mode is used for the new file
+// (the process's umask applies).
+//
+// Unlike [os.Create], if the file already exists an error is created rather
+// than the file being opened and truncated.
+//
+// [os.Create]: https://pkg.go.dev/os#Create
+func (r *Root) Create(path string, flags int, mode os.FileMode) (*os.File, error) {
+ unixMode, err := toUnixMode(mode, false)
+ if err != nil {
+ return nil, err
+ }
+ return fdutils.WithFileFd(r.inner, func(rootFd uintptr) (*os.File, error) {
+ handleFd, err := libpathrs.InRootCreat(rootFd, path, flags, unixMode)
+ if err != nil {
+ return nil, err
+ }
+ return fdutils.MkFile(handleFd)
+ })
+}
+
+// Rename two paths within a [Root]'s directory tree. The flags argument is
+// identical to the RENAME_* flags to the renameat2(2) system call.
+func (r *Root) Rename(src, dst string, flags uint) error {
+ _, err := fdutils.WithFileFd(r.inner, func(rootFd uintptr) (struct{}, error) {
+ err := libpathrs.InRootRename(rootFd, src, dst, flags)
+ return struct{}{}, err
+ })
+ return err
+}
+
+// RemoveDir removes the named empty directory within a [Root]'s directory
+// tree.
+func (r *Root) RemoveDir(path string) error {
+ _, err := fdutils.WithFileFd(r.inner, func(rootFd uintptr) (struct{}, error) {
+ err := libpathrs.InRootRmdir(rootFd, path)
+ return struct{}{}, err
+ })
+ return err
+}
+
+// RemoveFile removes the named file within a [Root]'s directory tree.
+func (r *Root) RemoveFile(path string) error {
+ _, err := fdutils.WithFileFd(r.inner, func(rootFd uintptr) (struct{}, error) {
+ err := libpathrs.InRootUnlink(rootFd, path)
+ return struct{}{}, err
+ })
+ return err
+}
+
+// Remove removes the named file or (empty) directory within a [Root]'s
+// directory tree.
+//
+// This is effectively equivalent to [os.Remove].
+//
+// [os.Remove]: https://pkg.go.dev/os#Remove
+func (r *Root) Remove(path string) error {
+ // In order to match os.Remove's implementation we need to also do both
+ // syscalls unconditionally and adjust the error based on whether
+ // pathrs_inroot_rmdir() returned ENOTDIR.
+ unlinkErr := r.RemoveFile(path)
+ if unlinkErr == nil {
+ return nil
+ }
+ rmdirErr := r.RemoveDir(path)
+ if rmdirErr == nil {
+ return nil
+ }
+ // Both failed, adjust the error in the same way that os.Remove does.
+ err := rmdirErr
+ if errors.Is(err, syscall.ENOTDIR) {
+ err = unlinkErr
+ }
+ return err
+}
+
+// RemoveAll recursively deletes a path and all of its children.
+//
+// This is effectively equivalent to [os.RemoveAll].
+//
+// [os.RemoveAll]: https://pkg.go.dev/os#RemoveAll
+func (r *Root) RemoveAll(path string) error {
+ _, err := fdutils.WithFileFd(r.inner, func(rootFd uintptr) (struct{}, error) {
+ err := libpathrs.InRootRemoveAll(rootFd, path)
+ return struct{}{}, err
+ })
+ return err
+}
+
+// Mkdir creates a directory within a [Root]'s directory tree. The provided
+// mode is used for the new directory (the process's umask applies).
+//
+// This is effectively equivalent to [os.Mkdir].
+//
+// [os.Mkdir]: https://pkg.go.dev/os#Mkdir
+func (r *Root) Mkdir(path string, mode os.FileMode) error {
+ unixMode, err := toUnixMode(mode, false)
+ if err != nil {
+ return err
+ }
+
+ _, err = fdutils.WithFileFd(r.inner, func(rootFd uintptr) (struct{}, error) {
+ err := libpathrs.InRootMkdir(rootFd, path, unixMode)
+ return struct{}{}, err
+ })
+ return err
+}
+
+// MkdirAll creates a directory (and any parent path components if they don't
+// exist) within a [Root]'s directory tree. The provided mode is used for any
+// directories created by this function (the process's umask applies).
+//
+// This is effectively equivalent to [os.MkdirAll].
+//
+// [os.MkdirAll]: https://pkg.go.dev/os#MkdirAll
+func (r *Root) MkdirAll(path string, mode os.FileMode) (*Handle, error) {
+ unixMode, err := toUnixMode(mode, false)
+ if err != nil {
+ return nil, err
+ }
+
+ return fdutils.WithFileFd(r.inner, func(rootFd uintptr) (*Handle, error) {
+ handleFd, err := libpathrs.InRootMkdirAll(rootFd, path, unixMode)
+ if err != nil {
+ return nil, err
+ }
+ handleFile, err := fdutils.MkFile(handleFd)
+ if err != nil {
+ return nil, err
+ }
+ return &Handle{inner: handleFile}, err
+ })
+}
+
+// Mknod creates a new device inode of the given type within a [Root]'s
+// directory tree. The provided mode is used for the new directory (the
+// process's umask applies).
+//
+// This is effectively equivalent to [unix.Mknod].
+//
+// [unix.Mknod]: https://pkg.go.dev/golang.org/x/sys/unix#Mknod
+func (r *Root) Mknod(path string, mode os.FileMode, dev uint64) error {
+ unixMode, err := toUnixMode(mode, true)
+ if err != nil {
+ return err
+ }
+
+ _, err = fdutils.WithFileFd(r.inner, func(rootFd uintptr) (struct{}, error) {
+ err := libpathrs.InRootMknod(rootFd, path, unixMode, dev)
+ return struct{}{}, err
+ })
+ return err
+}
+
+// Symlink creates a symlink within a [Root]'s directory tree. The symlink is
+// created at path and is a link to target.
+//
+// This is effectively equivalent to [os.Symlink].
+//
+// [os.Symlink]: https://pkg.go.dev/os#Symlink
+func (r *Root) Symlink(path, target string) error {
+ _, err := fdutils.WithFileFd(r.inner, func(rootFd uintptr) (struct{}, error) {
+ err := libpathrs.InRootSymlink(rootFd, path, target)
+ return struct{}{}, err
+ })
+ return err
+}
+
+// Hardlink creates a hardlink within a [Root]'s directory tree. The hardlink
+// is created at path and is a link to target. Both paths are within the
+// [Root]'s directory tree (you cannot hardlink to a different [Root] or the
+// host).
+//
+// This is effectively equivalent to [os.Link].
+//
+// [os.Link]: https://pkg.go.dev/os#Link
+func (r *Root) Hardlink(path, target string) error {
+ _, err := fdutils.WithFileFd(r.inner, func(rootFd uintptr) (struct{}, error) {
+ err := libpathrs.InRootHardlink(rootFd, path, target)
+ return struct{}{}, err
+ })
+ return err
+}
+
+// Readlink returns the target of a symlink with a [Root]'s directory tree.
+//
+// This is effectively equivalent to [os.Readlink].
+//
+// [os.Readlink]: https://pkg.go.dev/os#Readlink
+func (r *Root) Readlink(path string) (string, error) {
+ return fdutils.WithFileFd(r.inner, func(rootFd uintptr) (string, error) {
+ return libpathrs.InRootReadlink(rootFd, path)
+ })
+}
+
+// IntoFile unwraps the [Root] into its underlying [os.File].
+//
+// It is critical that you do not operate on this file descriptor yourself,
+// because the security properties of libpathrs depend on users doing all
+// relevant filesystem operations through libpathrs.
+//
+// This operation returns the internal [os.File] of the [Root] directly, so
+// calling [Root.Close] will also close any copies of the returned [os.File].
+// If you want to get an independent copy, use [Root.Clone] followed by
+// [Root.IntoFile] on the cloned [Root].
+//
+// [os.File]: https://pkg.go.dev/os#File
+func (r *Root) IntoFile() *os.File {
+ // TODO: Figure out if we really don't want to make a copy.
+ // TODO: We almost certainly want to clear r.inner here, but we can't do
+ // that easily atomically (we could use atomic.Value but that'll make
+ // things quite a bit uglier).
+ return r.inner
+}
+
+// Clone creates a copy of a [Root] handle, such that it has a separate
+// lifetime to the original (while referring to the same underlying directory).
+func (r *Root) Clone() (*Root, error) {
+ return RootFromFile(r.inner)
+}
+
+// Close frees all of the resources used by the [Root] handle.
+func (r *Root) Close() error {
+ return r.inner.Close()
+}
diff --git a/vendor/cyphar.com/go-pathrs/utils_linux.go b/vendor/cyphar.com/go-pathrs/utils_linux.go
new file mode 100644
index 0000000000..2208d608f8
--- /dev/null
+++ b/vendor/cyphar.com/go-pathrs/utils_linux.go
@@ -0,0 +1,56 @@
+//go:build linux
+
+// SPDX-License-Identifier: MPL-2.0
+/*
+ * libpathrs: safe path resolution on Linux
+ * Copyright (C) 2019-2025 Aleksa Sarai
+ * Copyright (C) 2019-2025 SUSE LLC
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package pathrs
+
+import (
+ "fmt"
+ "os"
+
+ "golang.org/x/sys/unix"
+)
+
+//nolint:cyclop // this function needs to handle a lot of cases
+func toUnixMode(mode os.FileMode, needsType bool) (uint32, error) {
+ sysMode := uint32(mode.Perm())
+ switch mode & os.ModeType { //nolint:exhaustive // we only care about ModeType bits
+ case 0:
+ if needsType {
+ sysMode |= unix.S_IFREG
+ }
+ case os.ModeDir:
+ sysMode |= unix.S_IFDIR
+ case os.ModeSymlink:
+ sysMode |= unix.S_IFLNK
+ case os.ModeCharDevice | os.ModeDevice:
+ sysMode |= unix.S_IFCHR
+ case os.ModeDevice:
+ sysMode |= unix.S_IFBLK
+ case os.ModeNamedPipe:
+ sysMode |= unix.S_IFIFO
+ case os.ModeSocket:
+ sysMode |= unix.S_IFSOCK
+ default:
+ return 0, fmt.Errorf("invalid mode filetype %+o", mode)
+ }
+ if mode&os.ModeSetuid != 0 {
+ sysMode |= unix.S_ISUID
+ }
+ if mode&os.ModeSetgid != 0 {
+ sysMode |= unix.S_ISGID
+ }
+ if mode&os.ModeSticky != 0 {
+ sysMode |= unix.S_ISVTX
+ }
+ return sysMode, nil
+}
diff --git a/vendor/github.com/cyphar/filepath-securejoin/.golangci.yml b/vendor/github.com/cyphar/filepath-securejoin/.golangci.yml
index e965034ed3..3e8dd99bd7 100644
--- a/vendor/github.com/cyphar/filepath-securejoin/.golangci.yml
+++ b/vendor/github.com/cyphar/filepath-securejoin/.golangci.yml
@@ -9,6 +9,10 @@
version: "2"
+run:
+ build-tags:
+ - libpathrs
+
linters:
enable:
- asasalint
diff --git a/vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md b/vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md
index 3faee0bc55..734cf61e32 100644
--- a/vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md
+++ b/vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md
@@ -4,7 +4,64 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
-## [Unreleased 0.5.z] ##
+## [Unreleased] ##
+
+## [0.6.0] - 2025-11-03 ##
+
+> By the Power of Greyskull!
+
+While quite small code-wise, this release marks a very key point in the
+development of filepath-securejoin.
+
+filepath-securejoin was originally intended (back in 2017) to simply be a
+single-purpose library that would take some common code used in container
+runtimes (specifically, Docker's `FollowSymlinksInScope`) and make it more
+general-purpose (with the eventual goals of it ending up in the Go stdlib).
+
+Of course, I quickly discovered that this problem was actually far more
+complicated to solve when dealing with racing attackers, which lead to me
+developing `openat2(2)` and [libpathrs][]. I had originally planned for
+libpathrs to completely replace filepath-securejoin "once it was ready" but in
+the interim we needed to fix several race attacks in runc as part of security
+advisories. Obviously we couldn't require the usage of a pre-0.1 Rust library
+in runc so it was necessary to port bits of libpathrs into filepath-securejoin.
+(Ironically the first prototypes of libpathrs were originally written in Go and
+then rewritten to Rust, so the code in filepath-securejoin is actually Go code
+that was rewritten to Rust then re-rewritten to Go.)
+
+It then became clear that pure-Go libraries will likely not be willing to
+require CGo for all of their builds, so it was necessary to accept that
+filepath-securejoin will need to stay. As such, in v0.5.0 we provided more
+pure-Go implementations of features from libpathrs but moved them into
+`pathrs-lite` subpackage to clarify what purpose these helpers serve.
+
+This release finally closes the loop and makes it so that pathrs-lite can
+transparently use libpathrs (via a `libpathrs` build-tag). This means that
+upstream libraries can use the pure Go version if they prefer, but downstreams
+(either downstream library users or even downstream distributions) are able to
+migrate to libpathrs for all usages of pathrs-lite in an entire Go binary.
+
+I should make it clear that I do not plan to port the rest of libpathrs to Go,
+as I do not wish to maintain two copies of the same codebase. pathrs-lite
+already provides the core essentials necessary to operate on paths safely for
+most modern systems. Users who want additional hardening or more ergonomic APIs
+are free to use [`cyphar.com/go-pathrs`][go-pathrs] (libpathrs's Go bindings).
+
+[libpathrs]: https://github.com/cyphar/libpathrs
+[go-pathrs]: https://cyphar.com/go-pathrs
+
+### Breaking ###
+- The deprecated `MkdirAll`, `MkdirAllHandle`, `OpenInRoot`, `OpenatInRoot` and
+ `Reopen` wrappers have been removed. Please switch to using `pathrs-lite`
+ directly.
+
+### Added ###
+- `pathrs-lite` now has support for using [libpathrs][libpathrs] as a backend.
+ This is opt-in and can be enabled at build time with the `libpathrs` build
+ tag. The intention is to allow for downstream libraries and other projects to
+ make use of the pure-Go `github.com/cyphar/filepath-securejoin/pathrs-lite`
+ package and distributors can then opt-in to using `libpathrs` for the entire
+ binary if they wish.
## [0.5.1] - 2025-10-31 ##
@@ -383,7 +440,8 @@ This is our first release of `github.com/cyphar/filepath-securejoin`,
containing a full implementation with a coverage of 93.5% (the only missing
cases are the error cases, which are hard to mocktest at the moment).
-[Unreleased 0.5.z]: https://github.com/cyphar/filepath-securejoin/compare/v0.5.1...release-0.5
+[Unreleased]: https://github.com/cyphar/filepath-securejoin/compare/v0.6.0...HEAD
+[0.6.0]: https://github.com/cyphar/filepath-securejoin/compare/v0.5.1...v0.6.0
[0.5.1]: https://github.com/cyphar/filepath-securejoin/compare/v0.5.0...v0.5.1
[0.5.0]: https://github.com/cyphar/filepath-securejoin/compare/v0.4.1...v0.5.0
[0.4.1]: https://github.com/cyphar/filepath-securejoin/compare/v0.4.0...v0.4.1
diff --git a/vendor/github.com/cyphar/filepath-securejoin/VERSION b/vendor/github.com/cyphar/filepath-securejoin/VERSION
index 4b9fcbec10..a918a2aa18 100644
--- a/vendor/github.com/cyphar/filepath-securejoin/VERSION
+++ b/vendor/github.com/cyphar/filepath-securejoin/VERSION
@@ -1 +1 @@
-0.5.1
+0.6.0
diff --git a/vendor/github.com/cyphar/filepath-securejoin/deprecated_linux.go b/vendor/github.com/cyphar/filepath-securejoin/deprecated_linux.go
deleted file mode 100644
index 3e427b1640..0000000000
--- a/vendor/github.com/cyphar/filepath-securejoin/deprecated_linux.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-
-//go:build linux
-
-// Copyright (C) 2024-2025 Aleksa Sarai
-// Copyright (C) 2024-2025 SUSE LLC
-//
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at https://mozilla.org/MPL/2.0/.
-
-package securejoin
-
-import (
- "github.com/cyphar/filepath-securejoin/pathrs-lite"
-)
-
-var (
- // MkdirAll is a wrapper around [pathrs.MkdirAll].
- //
- // Deprecated: You should use [pathrs.MkdirAll] directly instead. This
- // wrapper will be removed in filepath-securejoin v0.6.
- MkdirAll = pathrs.MkdirAll
-
- // MkdirAllHandle is a wrapper around [pathrs.MkdirAllHandle].
- //
- // Deprecated: You should use [pathrs.MkdirAllHandle] directly instead.
- // This wrapper will be removed in filepath-securejoin v0.6.
- MkdirAllHandle = pathrs.MkdirAllHandle
-
- // OpenInRoot is a wrapper around [pathrs.OpenInRoot].
- //
- // Deprecated: You should use [pathrs.OpenInRoot] directly instead. This
- // wrapper will be removed in filepath-securejoin v0.6.
- OpenInRoot = pathrs.OpenInRoot
-
- // OpenatInRoot is a wrapper around [pathrs.OpenatInRoot].
- //
- // Deprecated: You should use [pathrs.OpenatInRoot] directly instead. This
- // wrapper will be removed in filepath-securejoin v0.6.
- OpenatInRoot = pathrs.OpenatInRoot
-
- // Reopen is a wrapper around [pathrs.Reopen].
- //
- // Deprecated: You should use [pathrs.Reopen] directly instead. This
- // wrapper will be removed in filepath-securejoin v0.6.
- Reopen = pathrs.Reopen
-)
diff --git a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/README.md b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/README.md
index 1be727e75b..bb95b028c6 100644
--- a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/README.md
+++ b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/README.md
@@ -5,11 +5,13 @@ Go** implementation of the core bits of [libpathrs][]. This is not intended to
be a complete replacement for libpathrs, instead it is mainly intended to be
useful as a transition tool for existing Go projects.
-The long-term plan for `pathrs-lite` is to provide a build tag that will cause
-all `pathrs-lite` operations to call into libpathrs directly, thus removing
-code duplication for projects that wish to make use of libpathrs (and providing
-the ability for software packagers to opt-in to libpathrs support without
-needing to patch upstream).
+`pathrs-lite` also provides a very easy way to switch to `libpathrs` (even for
+downstreams where `pathrs-lite` is being used in a third-party package and is
+not interested in using CGo). At build time, if you use the `libpathrs` build
+tag then `pathrs-lite` will use `libpathrs` directly instead of the pure Go
+implementation. The two backends are functionally equivalent (and we have
+integration tests to verify this), so this migration should be very easy with
+no user-visible impact.
[libpathrs]: https://github.com/cyphar/libpathrs
diff --git a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/doc.go b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/doc.go
index d3d7451750..61411da37a 100644
--- a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/doc.go
+++ b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/doc.go
@@ -11,4 +11,6 @@
// Package pathrs (pathrs-lite) is a less complete pure Go implementation of
// some of the APIs provided by [libpathrs].
+//
+// [libpathrs]: https://github.com/cyphar/libpathrs
package pathrs
diff --git a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs/doc.go b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs/doc.go
new file mode 100644
index 0000000000..2ddb71e844
--- /dev/null
+++ b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs/doc.go
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build linux
+
+// Copyright (C) 2024-2025 Aleksa Sarai
+// Copyright (C) 2024-2025 SUSE LLC
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+// Package gopathrs is a less complete pure Go implementation of some of the
+// APIs provided by [libpathrs].
+//
+// [libpathrs]: https://github.com/cyphar/libpathrs
+package gopathrs
diff --git a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/lookup_linux.go b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs/lookup_linux.go
similarity index 98%
rename from vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/lookup_linux.go
rename to vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs/lookup_linux.go
index f47504e663..56480f0cee 100644
--- a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/lookup_linux.go
+++ b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs/lookup_linux.go
@@ -9,7 +9,7 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
-package pathrs
+package gopathrs
import (
"errors"
@@ -166,11 +166,11 @@ func (s *symlinkStack) PopTopSymlink() (*os.File, string, bool) {
return tailEntry.dir, tailEntry.remainingPath, true
}
-// partialLookupInRoot tries to lookup as much of the request path as possible
+// PartialLookupInRoot tries to lookup as much of the request path as possible
// within the provided root (a-la RESOLVE_IN_ROOT) and opens the final existing
// component of the requested path, returning a file handle to the final
// existing component and a string containing the remaining path components.
-func partialLookupInRoot(root fd.Fd, unsafePath string) (*os.File, string, error) {
+func PartialLookupInRoot(root fd.Fd, unsafePath string) (*os.File, string, error) {
return lookupInRoot(root, unsafePath, true)
}
diff --git a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/mkdir_linux.go b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs/mkdir_linux.go
similarity index 81%
rename from vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/mkdir_linux.go
rename to vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs/mkdir_linux.go
index f3c62b0dac..21a5593f44 100644
--- a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/mkdir_linux.go
+++ b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs/mkdir_linux.go
@@ -9,7 +9,7 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
-package pathrs
+package gopathrs
import (
"errors"
@@ -23,9 +23,12 @@ import (
"github.com/cyphar/filepath-securejoin/pathrs-lite/internal/fd"
"github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gocompat"
"github.com/cyphar/filepath-securejoin/pathrs-lite/internal/linux"
+ "github.com/cyphar/filepath-securejoin/pathrs-lite/internal/procfs"
)
-var errInvalidMode = errors.New("invalid permission mode")
+// ErrInvalidMode is returned from [MkdirAll] when the requested mode is
+// invalid.
+var ErrInvalidMode = errors.New("invalid permission mode")
// modePermExt is like os.ModePerm except that it also includes the set[ug]id
// and sticky bits.
@@ -45,11 +48,11 @@ func toUnixMode(mode os.FileMode) (uint32, error) {
}
// We don't allow file type bits.
if mode&os.ModeType != 0 {
- return 0, fmt.Errorf("%w %+.3o (%s): type bits not permitted", errInvalidMode, mode, mode)
+ return 0, fmt.Errorf("%w %+.3o (%s): type bits not permitted", ErrInvalidMode, mode, mode)
}
// We don't allow other unknown modes.
if mode&^modePermExt != 0 || sysMode&unix.S_IFMT != 0 {
- return 0, fmt.Errorf("%w %+.3o (%s): unknown mode bits", errInvalidMode, mode, mode)
+ return 0, fmt.Errorf("%w %+.3o (%s): unknown mode bits", ErrInvalidMode, mode, mode)
}
return sysMode, nil
}
@@ -84,11 +87,11 @@ func MkdirAllHandle(root *os.File, unsafePath string, mode os.FileMode) (_ *os.F
// users it seems more prudent to return an error so users notice that
// these bits will not be set.
if unixMode&^0o1777 != 0 {
- return nil, fmt.Errorf("%w for mkdir %+.3o: suid and sgid are ignored by mkdir", errInvalidMode, mode)
+ return nil, fmt.Errorf("%w for mkdir %+.3o: suid and sgid are ignored by mkdir", ErrInvalidMode, mode)
}
// Try to open as much of the path as possible.
- currentDir, remainingPath, err := partialLookupInRoot(root, unsafePath)
+ currentDir, remainingPath, err := PartialLookupInRoot(root, unsafePath)
defer func() {
if Err != nil {
_ = currentDir.Close()
@@ -117,7 +120,7 @@ func MkdirAllHandle(root *os.File, unsafePath string, mode os.FileMode) (_ *os.F
// Re-open the path to match the O_DIRECTORY reopen loop later (so that we
// always return a non-O_PATH handle). We also check that we actually got a
// directory.
- if reopenDir, err := Reopen(currentDir, unix.O_DIRECTORY|unix.O_CLOEXEC); errors.Is(err, unix.ENOTDIR) {
+ if reopenDir, err := procfs.ReopenFd(currentDir, unix.O_DIRECTORY|unix.O_CLOEXEC); errors.Is(err, unix.ENOTDIR) {
return nil, fmt.Errorf("cannot create subdirectories in %q: %w", currentDir.Name(), unix.ENOTDIR)
} else if err != nil {
return nil, fmt.Errorf("re-opening handle to %q: %w", currentDir.Name(), err)
@@ -207,40 +210,3 @@ func MkdirAllHandle(root *os.File, unsafePath string, mode os.FileMode) (_ *os.F
}
return currentDir, nil
}
-
-// MkdirAll is a race-safe alternative to the [os.MkdirAll] function,
-// where the new directory is guaranteed to be within the root directory (if an
-// attacker can move directories from inside the root to outside the root, the
-// created directory tree might be outside of the root but the key constraint
-// is that at no point will we walk outside of the directory tree we are
-// creating).
-//
-// Effectively, MkdirAll(root, unsafePath, mode) is equivalent to
-//
-// path, _ := securejoin.SecureJoin(root, unsafePath)
-// err := os.MkdirAll(path, mode)
-//
-// But is much safer. The above implementation is unsafe because if an attacker
-// can modify the filesystem tree between [SecureJoin] and [os.MkdirAll], it is
-// possible for MkdirAll to resolve unsafe symlink components and create
-// directories outside of the root.
-//
-// If you plan to open the directory after you have created it or want to use
-// an open directory handle as the root, you should use [MkdirAllHandle] instead.
-// This function is a wrapper around [MkdirAllHandle].
-//
-// [SecureJoin]: https://pkg.go.dev/github.com/cyphar/filepath-securejoin#SecureJoin
-func MkdirAll(root, unsafePath string, mode os.FileMode) error {
- rootDir, err := os.OpenFile(root, unix.O_PATH|unix.O_DIRECTORY|unix.O_CLOEXEC, 0)
- if err != nil {
- return err
- }
- defer rootDir.Close() //nolint:errcheck // close failures aren't critical here
-
- f, err := MkdirAllHandle(rootDir, unsafePath, mode)
- if err != nil {
- return err
- }
- _ = f.Close()
- return nil
-}
diff --git a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs/open_linux.go b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs/open_linux.go
new file mode 100644
index 0000000000..cd9632a958
--- /dev/null
+++ b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs/open_linux.go
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build linux
+
+// Copyright (C) 2024-2025 Aleksa Sarai
+// Copyright (C) 2024-2025 SUSE LLC
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+package gopathrs
+
+import (
+ "os"
+)
+
+// OpenatInRoot is equivalent to [OpenInRoot], except that the root is provided
+// using an *[os.File] handle, to ensure that the correct root directory is used.
+func OpenatInRoot(root *os.File, unsafePath string) (*os.File, error) {
+ handle, err := completeLookupInRoot(root, unsafePath)
+ if err != nil {
+ return nil, &os.PathError{Op: "securejoin.OpenInRoot", Path: unsafePath, Err: err}
+ }
+ return handle, nil
+}
diff --git a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/openat2_linux.go b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs/openat2_linux.go
similarity index 99%
rename from vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/openat2_linux.go
rename to vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs/openat2_linux.go
index 937bc435f2..b80ecd0895 100644
--- a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/openat2_linux.go
+++ b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs/openat2_linux.go
@@ -9,7 +9,7 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
-package pathrs
+package gopathrs
import (
"errors"
diff --git a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/mkdir.go b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/mkdir.go
new file mode 100644
index 0000000000..b43169564a
--- /dev/null
+++ b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/mkdir.go
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build linux
+
+// Copyright (C) 2024-2025 Aleksa Sarai
+// Copyright (C) 2024-2025 SUSE LLC
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+package pathrs
+
+import (
+ "os"
+
+ "golang.org/x/sys/unix"
+)
+
+// MkdirAll is a race-safe alternative to the [os.MkdirAll] function,
+// where the new directory is guaranteed to be within the root directory (if an
+// attacker can move directories from inside the root to outside the root, the
+// created directory tree might be outside of the root but the key constraint
+// is that at no point will we walk outside of the directory tree we are
+// creating).
+//
+// Effectively, MkdirAll(root, unsafePath, mode) is equivalent to
+//
+// path, _ := securejoin.SecureJoin(root, unsafePath)
+// err := os.MkdirAll(path, mode)
+//
+// But is much safer. The above implementation is unsafe because if an attacker
+// can modify the filesystem tree between [SecureJoin] and [os.MkdirAll], it is
+// possible for MkdirAll to resolve unsafe symlink components and create
+// directories outside of the root.
+//
+// If you plan to open the directory after you have created it or want to use
+// an open directory handle as the root, you should use [MkdirAllHandle] instead.
+// This function is a wrapper around [MkdirAllHandle].
+//
+// [SecureJoin]: https://pkg.go.dev/github.com/cyphar/filepath-securejoin#SecureJoin
+func MkdirAll(root, unsafePath string, mode os.FileMode) error {
+ rootDir, err := os.OpenFile(root, unix.O_PATH|unix.O_DIRECTORY|unix.O_CLOEXEC, 0)
+ if err != nil {
+ return err
+ }
+ defer rootDir.Close() //nolint:errcheck // close failures aren't critical here
+
+ f, err := MkdirAllHandle(rootDir, unsafePath, mode)
+ if err != nil {
+ return err
+ }
+ _ = f.Close()
+ return nil
+}
diff --git a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/mkdir_libpathrs.go b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/mkdir_libpathrs.go
new file mode 100644
index 0000000000..f864dbc8f3
--- /dev/null
+++ b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/mkdir_libpathrs.go
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build libpathrs
+
+// Copyright (C) 2024-2025 Aleksa Sarai
+// Copyright (C) 2024-2025 SUSE LLC
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+package pathrs
+
+import (
+ "os"
+
+ "cyphar.com/go-pathrs"
+)
+
+// MkdirAllHandle is equivalent to [MkdirAll], except that it is safer to use
+// in two respects:
+//
+// - The caller provides the root directory as an *[os.File] (preferably O_PATH)
+// handle. This means that the caller can be sure which root directory is
+// being used. Note that this can be emulated by using /proc/self/fd/... as
+// the root path with [os.MkdirAll].
+//
+// - Once all of the directories have been created, an *[os.File] O_PATH handle
+// to the directory at unsafePath is returned to the caller. This is done in
+// an effectively-race-free way (an attacker would only be able to swap the
+// final directory component), which is not possible to emulate with
+// [MkdirAll].
+//
+// In addition, the returned handle is obtained far more efficiently than doing
+// a brand new lookup of unsafePath (such as with [SecureJoin] or openat2) after
+// doing [MkdirAll]. If you intend to open the directory after creating it, you
+// should use MkdirAllHandle.
+//
+// [SecureJoin]: https://pkg.go.dev/github.com/cyphar/filepath-securejoin#SecureJoin
+func MkdirAllHandle(root *os.File, unsafePath string, mode os.FileMode) (*os.File, error) {
+ rootRef, err := pathrs.RootFromFile(root)
+ if err != nil {
+ return nil, err
+ }
+ defer rootRef.Close() //nolint:errcheck // close failures aren't critical here
+
+ handle, err := rootRef.MkdirAll(unsafePath, mode)
+ if err != nil {
+ return nil, err
+ }
+ return handle.IntoFile(), nil
+}
diff --git a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/mkdir_purego.go b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/mkdir_purego.go
new file mode 100644
index 0000000000..0369dfe7e6
--- /dev/null
+++ b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/mkdir_purego.go
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build linux && !libpathrs
+
+// Copyright (C) 2024-2025 Aleksa Sarai
+// Copyright (C) 2024-2025 SUSE LLC
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+package pathrs
+
+import (
+ "os"
+
+ "github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs"
+)
+
+// MkdirAllHandle is equivalent to [MkdirAll], except that it is safer to use
+// in two respects:
+//
+// - The caller provides the root directory as an *[os.File] (preferably O_PATH)
+// handle. This means that the caller can be sure which root directory is
+// being used. Note that this can be emulated by using /proc/self/fd/... as
+// the root path with [os.MkdirAll].
+//
+// - Once all of the directories have been created, an *[os.File] O_PATH handle
+// to the directory at unsafePath is returned to the caller. This is done in
+// an effectively-race-free way (an attacker would only be able to swap the
+// final directory component), which is not possible to emulate with
+// [MkdirAll].
+//
+// In addition, the returned handle is obtained far more efficiently than doing
+// a brand new lookup of unsafePath (such as with [SecureJoin] or openat2) after
+// doing [MkdirAll]. If you intend to open the directory after creating it, you
+// should use MkdirAllHandle.
+//
+// [SecureJoin]: https://pkg.go.dev/github.com/cyphar/filepath-securejoin#SecureJoin
+func MkdirAllHandle(root *os.File, unsafePath string, mode os.FileMode) (*os.File, error) {
+ return gopathrs.MkdirAllHandle(root, unsafePath, mode)
+}
diff --git a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/open_linux.go b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/open.go
similarity index 57%
rename from vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/open_linux.go
rename to vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/open.go
index 7492d8cfa0..41b628907e 100644
--- a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/open_linux.go
+++ b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/open.go
@@ -15,20 +15,8 @@ import (
"os"
"golang.org/x/sys/unix"
-
- "github.com/cyphar/filepath-securejoin/pathrs-lite/internal/procfs"
)
-// OpenatInRoot is equivalent to [OpenInRoot], except that the root is provided
-// using an *[os.File] handle, to ensure that the correct root directory is used.
-func OpenatInRoot(root *os.File, unsafePath string) (*os.File, error) {
- handle, err := completeLookupInRoot(root, unsafePath)
- if err != nil {
- return nil, &os.PathError{Op: "securejoin.OpenInRoot", Path: unsafePath, Err: err}
- }
- return handle, nil
-}
-
// OpenInRoot safely opens the provided unsafePath within the root.
// Effectively, OpenInRoot(root, unsafePath) is equivalent to
//
@@ -55,20 +43,3 @@ func OpenInRoot(root, unsafePath string) (*os.File, error) {
defer rootDir.Close() //nolint:errcheck // close failures aren't critical here
return OpenatInRoot(rootDir, unsafePath)
}
-
-// Reopen takes an *[os.File] handle and re-opens it through /proc/self/fd.
-// Reopen(file, flags) is effectively equivalent to
-//
-// fdPath := fmt.Sprintf("/proc/self/fd/%d", file.Fd())
-// os.OpenFile(fdPath, flags|unix.O_CLOEXEC)
-//
-// But with some extra hardenings to ensure that we are not tricked by a
-// maliciously-configured /proc mount. While this attack scenario is not
-// common, in container runtimes it is possible for higher-level runtimes to be
-// tricked into configuring an unsafe /proc that can be used to attack file
-// operations. See [CVE-2019-19921] for more details.
-//
-// [CVE-2019-19921]: https://github.com/advisories/GHSA-fh74-hm69-rqjw
-func Reopen(handle *os.File, flags int) (*os.File, error) {
- return procfs.ReopenFd(handle, flags)
-}
diff --git a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/open_libpathrs.go b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/open_libpathrs.go
new file mode 100644
index 0000000000..53352000e6
--- /dev/null
+++ b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/open_libpathrs.go
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build libpathrs
+
+// Copyright (C) 2024-2025 Aleksa Sarai
+// Copyright (C) 2024-2025 SUSE LLC
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+package pathrs
+
+import (
+ "os"
+
+ "cyphar.com/go-pathrs"
+)
+
+// OpenatInRoot is equivalent to [OpenInRoot], except that the root is provided
+// using an *[os.File] handle, to ensure that the correct root directory is used.
+func OpenatInRoot(root *os.File, unsafePath string) (*os.File, error) {
+ rootRef, err := pathrs.RootFromFile(root)
+ if err != nil {
+ return nil, err
+ }
+ defer rootRef.Close() //nolint:errcheck // close failures aren't critical here
+
+ handle, err := rootRef.Resolve(unsafePath)
+ if err != nil {
+ return nil, err
+ }
+ return handle.IntoFile(), nil
+}
+
+// Reopen takes an *[os.File] handle and re-opens it through /proc/self/fd.
+// Reopen(file, flags) is effectively equivalent to
+//
+// fdPath := fmt.Sprintf("/proc/self/fd/%d", file.Fd())
+// os.OpenFile(fdPath, flags|unix.O_CLOEXEC)
+//
+// But with some extra hardenings to ensure that we are not tricked by a
+// maliciously-configured /proc mount. While this attack scenario is not
+// common, in container runtimes it is possible for higher-level runtimes to be
+// tricked into configuring an unsafe /proc that can be used to attack file
+// operations. See [CVE-2019-19921] for more details.
+//
+// [CVE-2019-19921]: https://github.com/advisories/GHSA-fh74-hm69-rqjw
+func Reopen(file *os.File, flags int) (*os.File, error) {
+ handle, err := pathrs.HandleFromFile(file)
+ if err != nil {
+ return nil, err
+ }
+ defer handle.Close() //nolint:errcheck // close failures aren't critical here
+
+ return handle.OpenFile(flags)
+}
diff --git a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/open_purego.go b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/open_purego.go
new file mode 100644
index 0000000000..6d1be12ce5
--- /dev/null
+++ b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/open_purego.go
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build linux && !libpathrs
+
+// Copyright (C) 2024-2025 Aleksa Sarai
+// Copyright (C) 2024-2025 SUSE LLC
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+package pathrs
+
+import (
+ "os"
+
+ "github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs"
+ "github.com/cyphar/filepath-securejoin/pathrs-lite/internal/procfs"
+)
+
+// OpenatInRoot is equivalent to [OpenInRoot], except that the root is provided
+// using an *[os.File] handle, to ensure that the correct root directory is used.
+func OpenatInRoot(root *os.File, unsafePath string) (*os.File, error) {
+ return gopathrs.OpenatInRoot(root, unsafePath)
+}
+
+// Reopen takes an *[os.File] handle and re-opens it through /proc/self/fd.
+// Reopen(file, flags) is effectively equivalent to
+//
+// fdPath := fmt.Sprintf("/proc/self/fd/%d", file.Fd())
+// os.OpenFile(fdPath, flags|unix.O_CLOEXEC)
+//
+// But with some extra hardenings to ensure that we are not tricked by a
+// maliciously-configured /proc mount. While this attack scenario is not
+// common, in container runtimes it is possible for higher-level runtimes to be
+// tricked into configuring an unsafe /proc that can be used to attack file
+// operations. See [CVE-2019-19921] for more details.
+//
+// [CVE-2019-19921]: https://github.com/advisories/GHSA-fh74-hm69-rqjw
+func Reopen(handle *os.File, flags int) (*os.File, error) {
+ return procfs.ReopenFd(handle, flags)
+}
diff --git a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/procfs/procfs_libpathrs.go b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/procfs/procfs_libpathrs.go
new file mode 100644
index 0000000000..6c4df3763b
--- /dev/null
+++ b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/procfs/procfs_libpathrs.go
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build libpathrs
+
+// Copyright (C) 2024-2025 Aleksa Sarai
+// Copyright (C) 2024-2025 SUSE LLC
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+// Package procfs provides a safe API for operating on /proc on Linux.
+package procfs
+
+import (
+ "os"
+ "strconv"
+
+ "cyphar.com/go-pathrs/procfs"
+ "golang.org/x/sys/unix"
+)
+
+// ProcThreadSelfCloser is a callback that needs to be called when you are done
+// operating on an [os.File] fetched using [Handle.OpenThreadSelf].
+//
+// [os.File]: https://pkg.go.dev/os#File
+type ProcThreadSelfCloser = procfs.ThreadCloser
+
+// Handle is a wrapper around an *os.File handle to "/proc", which can be used
+// to do further procfs-related operations in a safe way.
+type Handle struct {
+ inner *procfs.Handle
+}
+
+// Close close the resources associated with this [Handle]. Note that if this
+// [Handle] was created with [OpenProcRoot], on some kernels the underlying
+// procfs handle is cached and so this Close operation may be a no-op. However,
+// you should always call Close on [Handle]s once you are done with them.
+func (proc *Handle) Close() error { return proc.inner.Close() }
+
+// OpenProcRoot tries to open a "safer" handle to "/proc" (i.e., one with the
+// "subset=pid" mount option applied, available from Linux 5.8). Unless you
+// plan to do many [Handle.OpenRoot] operations, users should prefer to use
+// this over [OpenUnsafeProcRoot] which is far more dangerous to keep open.
+//
+// If a safe handle cannot be opened, OpenProcRoot will fall back to opening a
+// regular "/proc" handle.
+//
+// Note that using [Handle.OpenRoot] will still work with handles returned by
+// this function. If a subpath cannot be operated on with a safe "/proc"
+// handle, then [OpenUnsafeProcRoot] will be called internally and a temporary
+// unsafe handle will be used.
+func OpenProcRoot() (*Handle, error) {
+ proc, err := procfs.Open()
+ if err != nil {
+ return nil, err
+ }
+ return &Handle{inner: proc}, nil
+}
+
+// OpenUnsafeProcRoot opens a handle to "/proc" without any overmounts or
+// masked paths. You must be extremely careful to make sure this handle is
+// never leaked to a container and that you program cannot be tricked into
+// writing to arbitrary paths within it.
+//
+// This is not necessary if you just wish to use [Handle.OpenRoot], as handles
+// returned by [OpenProcRoot] will fall back to using a *temporary* unsafe
+// handle in that case. You should only really use this if you need to do many
+// operations with [Handle.OpenRoot] and the performance overhead of making
+// many procfs handles is an issue. If you do use OpenUnsafeProcRoot, you
+// should make sure to close the handle as soon as possible to avoid
+// known-fd-number attacks.
+func OpenUnsafeProcRoot() (*Handle, error) {
+ proc, err := procfs.Open(procfs.UnmaskedProcRoot)
+ if err != nil {
+ return nil, err
+ }
+ return &Handle{inner: proc}, nil
+}
+
+// OpenThreadSelf returns a handle to "/proc/thread-self/" (or an
+// equivalent handle on older kernels where "/proc/thread-self" doesn't exist).
+// Once finished with the handle, you must call the returned closer function
+// ([runtime.UnlockOSThread]). You must not pass the returned *os.File to other
+// Go threads or use the handle after calling the closer.
+//
+// [runtime.UnlockOSThread]: https://pkg.go.dev/runtime#UnlockOSThread
+func (proc *Handle) OpenThreadSelf(subpath string) (*os.File, ProcThreadSelfCloser, error) {
+ return proc.inner.OpenThreadSelf(subpath, unix.O_PATH|unix.O_NOFOLLOW)
+}
+
+// OpenSelf returns a handle to /proc/self/.
+//
+// Note that in Go programs with non-homogenous threads, this may result in
+// spurious errors. If you are monkeying around with APIs that are
+// thread-specific, you probably want to use [Handle.OpenThreadSelf] instead
+// which will guarantee that the handle refers to the same thread as the caller
+// is executing on.
+func (proc *Handle) OpenSelf(subpath string) (*os.File, error) {
+ return proc.inner.OpenSelf(subpath, unix.O_PATH|unix.O_NOFOLLOW)
+}
+
+// OpenRoot returns a handle to /proc/.
+//
+// You should only use this when you need to operate on global procfs files
+// (such as sysctls in /proc/sys). Unlike [Handle.OpenThreadSelf],
+// [Handle.OpenSelf], and [Handle.OpenPid], the procfs handle used internally
+// for this operation will never use "subset=pid", which makes it a more juicy
+// target for [CVE-2024-21626]-style attacks (and doing something like opening
+// a directory with OpenRoot effectively leaks [OpenUnsafeProcRoot] as long as
+// the file descriptor is open).
+//
+// [CVE-2024-21626]: https://github.com/opencontainers/runc/security/advisories/GHSA-xr7r-f8xq-vfvv
+func (proc *Handle) OpenRoot(subpath string) (*os.File, error) {
+ return proc.inner.OpenRoot(subpath, unix.O_PATH|unix.O_NOFOLLOW)
+}
+
+// OpenPid returns a handle to /proc/$pid/ (pid can be a pid or tid).
+// This is mainly intended for usage when operating on other processes.
+//
+// You should not use this for the current thread, as special handling is
+// needed for /proc/thread-self (or /proc/self/task/) when dealing with
+// goroutine scheduling -- use [Handle.OpenThreadSelf] instead.
+//
+// To refer to the current thread-group, you should use prefer
+// [Handle.OpenSelf] to passing os.Getpid as the pid argument.
+func (proc *Handle) OpenPid(pid int, subpath string) (*os.File, error) {
+ return proc.inner.OpenPid(pid, subpath, unix.O_PATH|unix.O_NOFOLLOW)
+}
+
+// ProcSelfFdReadlink gets the real path of the given file by looking at
+// /proc/self/fd/ with [readlink]. It is effectively just shorthand for
+// something along the lines of:
+//
+// proc, err := procfs.OpenProcRoot()
+// if err != nil {
+// return err
+// }
+// link, err := proc.OpenThreadSelf(fmt.Sprintf("fd/%d", f.Fd()))
+// if err != nil {
+// return err
+// }
+// defer link.Close()
+// var buf [4096]byte
+// n, err := unix.Readlinkat(int(link.Fd()), "", buf[:])
+// if err != nil {
+// return err
+// }
+// pathname := buf[:n]
+//
+// [readlink]: https://pkg.go.dev/golang.org/x/sys/unix#Readlinkat
+func ProcSelfFdReadlink(f *os.File) (string, error) {
+ proc, err := procfs.Open()
+ if err != nil {
+ return "", err
+ }
+ defer proc.Close() //nolint:errcheck // close failures aren't critical here
+
+ fdPath := "fd/" + strconv.Itoa(int(f.Fd()))
+ return proc.Readlink(procfs.ProcThreadSelf, fdPath)
+}
diff --git a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/procfs/procfs_linux.go b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/procfs/procfs_purego.go
similarity index 99%
rename from vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/procfs/procfs_linux.go
rename to vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/procfs/procfs_purego.go
index ec187a414c..9383002f9a 100644
--- a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/procfs/procfs_linux.go
+++ b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/procfs/procfs_purego.go
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MPL-2.0
-//go:build linux
+//go:build linux && !libpathrs
// Copyright (C) 2024-2025 Aleksa Sarai
// Copyright (C) 2024-2025 SUSE LLC
diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/label/label_linux.go b/vendor/github.com/opencontainers/selinux/go-selinux/label/label_linux.go
index 1258c98ce7..95f29e21f4 100644
--- a/vendor/github.com/opencontainers/selinux/go-selinux/label/label_linux.go
+++ b/vendor/github.com/opencontainers/selinux/go-selinux/label/label_linux.go
@@ -18,7 +18,7 @@ var validOptions = map[string]bool{
"level": true,
}
-var ErrIncompatibleLabel = errors.New("Bad SELinux option z and Z can not be used together")
+var ErrIncompatibleLabel = errors.New("bad SELinux option: z and Z can not be used together")
// InitLabels returns the process label and file labels to be used within
// the container. A list of options can be passed into this function to alter
@@ -52,11 +52,11 @@ func InitLabels(options []string) (plabel string, mlabel string, retErr error) {
return "", selinux.PrivContainerMountLabel(), nil
}
if i := strings.Index(opt, ":"); i == -1 {
- return "", "", fmt.Errorf("Bad label option %q, valid options 'disable' or \n'user, role, level, type, filetype' followed by ':' and a value", opt)
+ return "", "", fmt.Errorf("bad label option %q, valid options 'disable' or \n'user, role, level, type, filetype' followed by ':' and a value", opt)
}
con := strings.SplitN(opt, ":", 2)
if !validOptions[con[0]] {
- return "", "", fmt.Errorf("Bad label option %q, valid options 'disable, user, role, level, type, filetype'", con[0])
+ return "", "", fmt.Errorf("bad label option %q, valid options 'disable, user, role, level, type, filetype'", con[0])
}
if con[0] == "filetype" {
mcon["type"] = con[1]
diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/selinux.go b/vendor/github.com/opencontainers/selinux/go-selinux/selinux.go
index 9f0740ef6f..15150d4752 100644
--- a/vendor/github.com/opencontainers/selinux/go-selinux/selinux.go
+++ b/vendor/github.com/opencontainers/selinux/go-selinux/selinux.go
@@ -153,7 +153,7 @@ func CalculateGlbLub(sourceRange, targetRange string) (string, error) {
// of the program is finished to guarantee another goroutine does not migrate to the current
// thread before execution is complete.
func SetExecLabel(label string) error {
- return writeCon(attrPath("exec"), label)
+ return writeConThreadSelf("attr/exec", label)
}
// SetTaskLabel sets the SELinux label for the current thread, or an error.
@@ -161,7 +161,7 @@ func SetExecLabel(label string) error {
// be wrapped in runtime.LockOSThread()/runtime.UnlockOSThread() to guarantee
// the current thread does not run in a new mislabeled thread.
func SetTaskLabel(label string) error {
- return writeCon(attrPath("current"), label)
+ return writeConThreadSelf("attr/current", label)
}
// SetSocketLabel takes a process label and tells the kernel to assign the
@@ -170,12 +170,12 @@ func SetTaskLabel(label string) error {
// the socket is created to guarantee another goroutine does not migrate
// to the current thread before execution is complete.
func SetSocketLabel(label string) error {
- return writeCon(attrPath("sockcreate"), label)
+ return writeConThreadSelf("attr/sockcreate", label)
}
// SocketLabel retrieves the current socket label setting
func SocketLabel() (string, error) {
- return readCon(attrPath("sockcreate"))
+ return readConThreadSelf("attr/sockcreate")
}
// PeerLabel retrieves the label of the client on the other side of a socket
@@ -198,7 +198,7 @@ func SetKeyLabel(label string) error {
// KeyLabel retrieves the current kernel keyring label setting
func KeyLabel() (string, error) {
- return readCon("/proc/self/attr/keycreate")
+ return keyLabel()
}
// Get returns the Context as a string
diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
index a607980724..6d7f8e270b 100644
--- a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
+++ b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
@@ -17,8 +17,11 @@ import (
"strings"
"sync"
- "github.com/opencontainers/selinux/pkg/pwalkdir"
+ "github.com/cyphar/filepath-securejoin/pathrs-lite"
+ "github.com/cyphar/filepath-securejoin/pathrs-lite/procfs"
"golang.org/x/sys/unix"
+
+ "github.com/opencontainers/selinux/pkg/pwalkdir"
)
const (
@@ -73,10 +76,6 @@ var (
mcsList: make(map[string]bool),
}
- // for attrPath()
- attrPathOnce sync.Once
- haveThreadSelf bool
-
// for policyRoot()
policyRootOnce sync.Once
policyRootVal string
@@ -256,48 +255,183 @@ func readConfig(target string) string {
return ""
}
-func isProcHandle(fh *os.File) error {
- var buf unix.Statfs_t
+func readConFd(in *os.File) (string, error) {
+ data, err := io.ReadAll(in)
+ if err != nil {
+ return "", err
+ }
+ return string(bytes.TrimSuffix(data, []byte{0})), nil
+}
- for {
- err := unix.Fstatfs(int(fh.Fd()), &buf)
- if err == nil {
- break
- }
- if err != unix.EINTR {
- return &os.PathError{Op: "fstatfs", Path: fh.Name(), Err: err}
- }
+func writeConFd(out *os.File, val string) error {
+ var err error
+ if val != "" {
+ _, err = out.Write([]byte(val))
+ } else {
+ _, err = out.Write(nil)
}
- if buf.Type != unix.PROC_SUPER_MAGIC {
- return fmt.Errorf("file %q is not on procfs", fh.Name())
+ return err
+}
+
+// openProcThreadSelf is a small wrapper around [procfs.Handle.OpenThreadSelf]
+// and [pathrs.Reopen] to make "one-shot opens" slightly more ergonomic. The
+// provided mode must be os.O_* flags to indicate what mode the returned file
+// should be opened with (flags like os.O_CREAT and os.O_EXCL are not
+// supported).
+//
+// If no error occurred, the returned handle is guaranteed to be exactly
+// /proc/thread-self/ with no tricky mounts or symlinks causing you to
+// operate on an unexpected path (with some caveats on pre-openat2 or
+// pre-fsopen kernels).
+func openProcThreadSelf(subpath string, mode int) (*os.File, procfs.ProcThreadSelfCloser, error) {
+ if subpath == "" {
+ return nil, nil, ErrEmptyPath
}
- return nil
-}
+ proc, err := procfs.OpenProcRoot()
+ if err != nil {
+ return nil, nil, err
+ }
+ defer proc.Close()
-func readCon(fpath string) (string, error) {
- if fpath == "" {
- return "", ErrEmptyPath
+ handle, closer, err := proc.OpenThreadSelf(subpath)
+ if err != nil {
+ return nil, nil, fmt.Errorf("open /proc/thread-self/%s handle: %w", subpath, err)
+ }
+ defer handle.Close() // we will return a re-opened handle
+
+ file, err := pathrs.Reopen(handle, mode)
+ if err != nil {
+ closer()
+ return nil, nil, fmt.Errorf("reopen /proc/thread-self/%s handle (%#x): %w", subpath, mode, err)
}
+ return file, closer, nil
+}
- in, err := os.Open(fpath)
+// Read the contents of /proc/thread-self/.
+func readConThreadSelf(fpath string) (string, error) {
+ in, closer, err := openProcThreadSelf(fpath, os.O_RDONLY|unix.O_CLOEXEC)
if err != nil {
return "", err
}
+ defer closer()
defer in.Close()
- if err := isProcHandle(in); err != nil {
+ return readConFd(in)
+}
+
+// Write to /proc/thread-self/.
+func writeConThreadSelf(fpath, val string) error {
+ if val == "" {
+ if !getEnabled() {
+ return nil
+ }
+ }
+
+ out, closer, err := openProcThreadSelf(fpath, os.O_WRONLY|unix.O_CLOEXEC)
+ if err != nil {
+ return err
+ }
+ defer closer()
+ defer out.Close()
+
+ return writeConFd(out, val)
+}
+
+// openProcSelf is a small wrapper around [procfs.Handle.OpenSelf] and
+// [pathrs.Reopen] to make "one-shot opens" slightly more ergonomic. The
+// provided mode must be os.O_* flags to indicate what mode the returned file
+// should be opened with (flags like os.O_CREAT and os.O_EXCL are not
+// supported).
+//
+// If no error occurred, the returned handle is guaranteed to be exactly
+// /proc/self/ with no tricky mounts or symlinks causing you to
+// operate on an unexpected path (with some caveats on pre-openat2 or
+// pre-fsopen kernels).
+func openProcSelf(subpath string, mode int) (*os.File, error) {
+ if subpath == "" {
+ return nil, ErrEmptyPath
+ }
+
+ proc, err := procfs.OpenProcRoot()
+ if err != nil {
+ return nil, err
+ }
+ defer proc.Close()
+
+ handle, err := proc.OpenSelf(subpath)
+ if err != nil {
+ return nil, fmt.Errorf("open /proc/self/%s handle: %w", subpath, err)
+ }
+ defer handle.Close() // we will return a re-opened handle
+
+ file, err := pathrs.Reopen(handle, mode)
+ if err != nil {
+ return nil, fmt.Errorf("reopen /proc/self/%s handle (%#x): %w", subpath, mode, err)
+ }
+ return file, nil
+}
+
+// Read the contents of /proc/self/.
+func readConSelf(fpath string) (string, error) {
+ in, err := openProcSelf(fpath, os.O_RDONLY|unix.O_CLOEXEC)
+ if err != nil {
return "", err
}
+ defer in.Close()
+
return readConFd(in)
}
-func readConFd(in *os.File) (string, error) {
- data, err := io.ReadAll(in)
+// Write to /proc/self/.
+func writeConSelf(fpath, val string) error {
+ if val == "" {
+ if !getEnabled() {
+ return nil
+ }
+ }
+
+ out, err := openProcSelf(fpath, os.O_WRONLY|unix.O_CLOEXEC)
if err != nil {
- return "", err
+ return err
}
- return string(bytes.TrimSuffix(data, []byte{0})), nil
+ defer out.Close()
+
+ return writeConFd(out, val)
+}
+
+// openProcPid is a small wrapper around [procfs.Handle.OpenPid] and
+// [pathrs.Reopen] to make "one-shot opens" slightly more ergonomic. The
+// provided mode must be os.O_* flags to indicate what mode the returned file
+// should be opened with (flags like os.O_CREAT and os.O_EXCL are not
+// supported).
+//
+// If no error occurred, the returned handle is guaranteed to be exactly
+// /proc/self/ with no tricky mounts or symlinks causing you to
+// operate on an unexpected path (with some caveats on pre-openat2 or
+// pre-fsopen kernels).
+func openProcPid(pid int, subpath string, mode int) (*os.File, error) {
+ if subpath == "" {
+ return nil, ErrEmptyPath
+ }
+
+ proc, err := procfs.OpenProcRoot()
+ if err != nil {
+ return nil, err
+ }
+ defer proc.Close()
+
+ handle, err := proc.OpenPid(pid, subpath)
+ if err != nil {
+ return nil, fmt.Errorf("open /proc/%d/%s handle: %w", pid, subpath, err)
+ }
+ defer handle.Close() // we will return a re-opened handle
+
+ file, err := pathrs.Reopen(handle, mode)
+ if err != nil {
+ return nil, fmt.Errorf("reopen /proc/%d/%s handle (%#x): %w", pid, subpath, mode, err)
+ }
+ return file, nil
}
// classIndex returns the int index for an object class in the loaded policy,
@@ -393,78 +527,34 @@ func lFileLabel(fpath string) (string, error) {
}
func setFSCreateLabel(label string) error {
- return writeCon(attrPath("fscreate"), label)
+ return writeConThreadSelf("attr/fscreate", label)
}
// fsCreateLabel returns the default label the kernel which the kernel is using
// for file system objects created by this task. "" indicates default.
func fsCreateLabel() (string, error) {
- return readCon(attrPath("fscreate"))
+ return readConThreadSelf("attr/fscreate")
}
// currentLabel returns the SELinux label of the current process thread, or an error.
func currentLabel() (string, error) {
- return readCon(attrPath("current"))
+ return readConThreadSelf("attr/current")
}
// pidLabel returns the SELinux label of the given pid, or an error.
func pidLabel(pid int) (string, error) {
- return readCon(fmt.Sprintf("/proc/%d/attr/current", pid))
+ it, err := openProcPid(pid, "attr/current", os.O_RDONLY|unix.O_CLOEXEC)
+ if err != nil {
+ return "", nil
+ }
+ defer it.Close()
+ return readConFd(it)
}
// ExecLabel returns the SELinux label that the kernel will use for any programs
// that are executed by the current process thread, or an error.
func execLabel() (string, error) {
- return readCon(attrPath("exec"))
-}
-
-func writeCon(fpath, val string) error {
- if fpath == "" {
- return ErrEmptyPath
- }
- if val == "" {
- if !getEnabled() {
- return nil
- }
- }
-
- out, err := os.OpenFile(fpath, os.O_WRONLY, 0)
- if err != nil {
- return err
- }
- defer out.Close()
-
- if err := isProcHandle(out); err != nil {
- return err
- }
-
- if val != "" {
- _, err = out.Write([]byte(val))
- } else {
- _, err = out.Write(nil)
- }
- if err != nil {
- return err
- }
- return nil
-}
-
-func attrPath(attr string) string {
- // Linux >= 3.17 provides this
- const threadSelfPrefix = "/proc/thread-self/attr"
-
- attrPathOnce.Do(func() {
- st, err := os.Stat(threadSelfPrefix)
- if err == nil && st.Mode().IsDir() {
- haveThreadSelf = true
- }
- })
-
- if haveThreadSelf {
- return filepath.Join(threadSelfPrefix, attr)
- }
-
- return filepath.Join("/proc/self/task", strconv.Itoa(unix.Gettid()), "attr", attr)
+ return readConThreadSelf("exec")
}
// canonicalizeContext takes a context string and writes it to the kernel
@@ -728,19 +818,29 @@ func peerLabel(fd uintptr) (string, error) {
// setKeyLabel takes a process label and tells the kernel to assign the
// label to the next kernel keyring that gets created
func setKeyLabel(label string) error {
- err := writeCon("/proc/self/attr/keycreate", label)
+ // Rather than using /proc/thread-self, we want to use /proc/self to
+ // operate on the thread-group leader.
+ err := writeConSelf("attr/keycreate", label)
if errors.Is(err, os.ErrNotExist) {
return nil
}
if label == "" && errors.Is(err, os.ErrPermission) {
return nil
}
- if errors.Is(err, unix.EACCES) && unix.Getuid() != unix.Gettid() {
+ if errors.Is(err, unix.EACCES) && unix.Getpid() != unix.Gettid() {
return ErrNotTGLeader
}
return err
}
+// KeyLabel retrieves the current kernel keyring label setting for this
+// thread-group.
+func keyLabel() (string, error) {
+ // Rather than using /proc/thread-self, we want to use /proc/self to
+ // operate on the thread-group leader.
+ return readConSelf("attr/keycreate")
+}
+
// get returns the Context as a string
func (c Context) get() string {
if l := c["level"]; l != "" {
diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go
index 0889fbe0e0..382244e503 100644
--- a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go
+++ b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go
@@ -3,15 +3,11 @@
package selinux
-func attrPath(string) string {
- return ""
-}
-
-func readCon(string) (string, error) {
+func readConThreadSelf(string) (string, error) {
return "", nil
}
-func writeCon(string, string) error {
+func writeConThreadSelf(string, string) error {
return nil
}
@@ -81,6 +77,10 @@ func setKeyLabel(string) error {
return nil
}
+func keyLabel() (string, error) {
+ return "", nil
+}
+
func (c Context) get() string {
return ""
}
diff --git a/vendor/github.com/openshift/library-go/pkg/crypto/crypto.go b/vendor/github.com/openshift/library-go/pkg/crypto/crypto.go
index 33a09ae16e..bff6155c2f 100644
--- a/vendor/github.com/openshift/library-go/pkg/crypto/crypto.go
+++ b/vendor/github.com/openshift/library-go/pkg/crypto/crypto.go
@@ -242,35 +242,41 @@ func ValidCipherSuites() []string {
sort.Strings(validCipherSuites)
return validCipherSuites
}
+
+// DefaultCiphers returns the default cipher suites for TLS connections.
+//
+// RECOMMENDATION: Instead of relying on this function directly, consumers should respect
+// TLSSecurityProfile settings from one of the OpenShift API configuration resources:
+// - For API servers: Use apiserver.config.openshift.io/cluster Spec.TLSSecurityProfile
+// - For ingress controllers: Use operator.openshift.io/v1 IngressController Spec.TLSSecurityProfile
+// - For kubelet: Use machineconfiguration.openshift.io/v1 KubeletConfig Spec.TLSSecurityProfile
+//
+// These API resources allow cluster administrators to choose between Old, Intermediate,
+// Modern, or Custom TLS profiles. Components should observe these settings.
func DefaultCiphers() []uint16 {
- // HTTP/2 mandates TLS 1.2 or higher with an AEAD cipher
- // suite (GCM, Poly1305) and ephemeral key exchange (ECDHE, DHE) for
- // perfect forward secrecy. Servers may provide additional cipher
- // suites for backwards compatibility with HTTP/1.1 clients.
- // See RFC7540, section 9.2 (Use of TLS Features) and Appendix A
- // (TLS 1.2 Cipher Suite Black List).
+ // Aligned with intermediate profile of the 5.7 version of the Mozilla Server
+ // Side TLS guidelines found at: https://ssl-config.mozilla.org/guidelines/5.7.json
+ //
+ // Latest guidelines: https://ssl-config.mozilla.org/guidelines/latest.json
+ //
+ // This profile provides strong security with wide compatibility.
+ // It requires TLS 1.2+ and uses only AEAD cipher suites (GCM, ChaCha20-Poly1305)
+ // with ECDHE key exchange for perfect forward secrecy.
+ //
+ // All CBC-mode ciphers have been removed due to padding oracle vulnerabilities.
+ // All RSA key exchange ciphers have been removed due to lack of perfect forward secrecy.
+ //
+ // HTTP/2 compliance: All ciphers are compliant with RFC7540, section 9.2.
return []uint16{
+ // TLS 1.2 cipher suites with ECDHE + AEAD
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
- tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, // required by http/2
+ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, // required by HTTP/2
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
- tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, // forbidden by http/2, not flagged by http2isBadCipher() in go1.8
- tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, // forbidden by http/2, not flagged by http2isBadCipher() in go1.8
- tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, // forbidden by http/2
- tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, // forbidden by http/2
- tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, // forbidden by http/2
- tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, // forbidden by http/2
- tls.TLS_RSA_WITH_AES_128_GCM_SHA256, // forbidden by http/2
- tls.TLS_RSA_WITH_AES_256_GCM_SHA384, // forbidden by http/2
- // the next one is in the intermediate suite, but go1.8 http2isBadCipher() complains when it is included at the recommended index
- // because it comes after ciphers forbidden by the http/2 spec
- // tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
- // tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, // forbidden by http/2, disabled to mitigate SWEET32 attack
- // tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA, // forbidden by http/2, disabled to mitigate SWEET32 attack
- tls.TLS_RSA_WITH_AES_128_CBC_SHA, // forbidden by http/2
- tls.TLS_RSA_WITH_AES_256_CBC_SHA, // forbidden by http/2
+
+ // TLS 1.3 cipher suites (negotiated automatically, not configurable)
tls.TLS_AES_128_GCM_SHA256,
tls.TLS_AES_256_GCM_SHA384,
tls.TLS_CHACHA20_POLY1305_SHA256,
diff --git a/vendor/github.com/openshift/library-go/pkg/operator/certrotation/signer.go b/vendor/github.com/openshift/library-go/pkg/operator/certrotation/signer.go
index 1cb4e55542..c2c8b8368f 100644
--- a/vendor/github.com/openshift/library-go/pkg/operator/certrotation/signer.go
+++ b/vendor/github.com/openshift/library-go/pkg/operator/certrotation/signer.go
@@ -188,7 +188,7 @@ func getValidityFromAnnotations(annotations map[string]string) (notBefore time.T
return notBefore, notAfter, fmt.Sprintf("bad expiry: %q", notAfterString)
}
notBeforeString := annotations[CertificateNotBeforeAnnotation]
- if len(notAfterString) == 0 {
+ if len(notBeforeString) == 0 {
return notBefore, notAfter, "missing notBefore"
}
notBefore, err = time.Parse(time.RFC3339, notBeforeString)
diff --git a/vendor/github.com/spf13/cobra/.golangci.yml b/vendor/github.com/spf13/cobra/.golangci.yml
index 2c8f4808c1..6acf8ab1ea 100644
--- a/vendor/github.com/spf13/cobra/.golangci.yml
+++ b/vendor/github.com/spf13/cobra/.golangci.yml
@@ -12,14 +12,20 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+version: "2"
+
run:
- deadline: 5m
+ timeout: 5m
+
+formatters:
+ enable:
+ - gofmt
+ - goimports
linters:
- disable-all: true
+ default: none
enable:
#- bodyclose
- # - deadcode ! deprecated since v1.49.0; replaced by 'unused'
#- depguard
#- dogsled
#- dupl
@@ -30,28 +36,24 @@ linters:
- goconst
- gocritic
#- gocyclo
- - gofmt
- - goimports
- #- gomnd
#- goprintffuncname
- gosec
- - gosimple
- govet
- ineffassign
#- lll
- misspell
+ #- mnd
#- nakedret
#- noctx
- nolintlint
#- rowserrcheck
- #- scopelint
- staticcheck
- #- structcheck ! deprecated since v1.49.0; replaced by 'unused'
- - stylecheck
- #- typecheck
- unconvert
#- unparam
- unused
- # - varcheck ! deprecated since v1.49.0; replaced by 'unused'
#- whitespace
- fast: false
+ exclusions:
+ presets:
+ - common-false-positives
+ - legacy
+ - std-error-handling
diff --git a/vendor/github.com/spf13/cobra/README.md b/vendor/github.com/spf13/cobra/README.md
index 71757151c3..8416275f48 100644
--- a/vendor/github.com/spf13/cobra/README.md
+++ b/vendor/github.com/spf13/cobra/README.md
@@ -1,8 +1,14 @@
-
-
+
Cobra is a library for creating powerful modern CLI applications.
+Visit Cobra.dev for extensive documentation
+
+
Cobra is used in many Go projects such as [Kubernetes](https://kubernetes.io/),
[Hugo](https://gohugo.io), and [GitHub CLI](https://github.com/cli/cli) to
name a few. [This list](site/content/projects_using_cobra.md) contains a more extensive list of projects using Cobra.
@@ -11,6 +17,20 @@ name a few. [This list](site/content/projects_using_cobra.md) contains a more ex
[](https://pkg.go.dev/github.com/spf13/cobra)
[](https://goreportcard.com/report/github.com/spf13/cobra)
[](https://gophers.slack.com/archives/CD3LP1199)
+
+
+
Supported by:
+
+
+
+
+
+
+### [Warp, the AI terminal for devs](https://www.warp.dev/cobra)
+[Try Cobra in Warp today](https://www.warp.dev/cobra)
+
+
+
# Overview
diff --git a/vendor/github.com/spf13/cobra/SECURITY.md b/vendor/github.com/spf13/cobra/SECURITY.md
new file mode 100644
index 0000000000..54e60c28c1
--- /dev/null
+++ b/vendor/github.com/spf13/cobra/SECURITY.md
@@ -0,0 +1,105 @@
+# Security Policy
+
+## Reporting a Vulnerability
+
+The `cobra` maintainers take security issues seriously and
+we appreciate your efforts to _**responsibly**_ disclose your findings.
+We will make every effort to swiftly respond and address concerns.
+
+To report a security vulnerability:
+
+1. **DO NOT** create a public GitHub issue for the vulnerability!
+2. **DO NOT** create a public GitHub Pull Request with a fix for the vulnerability!
+3. Send an email to `cobra-security@googlegroups.com`.
+4. Include the following details in your report:
+ - Description of the vulnerability
+ - Steps to reproduce
+ - Potential impact of the vulnerability (to your downstream project, to the Go ecosystem, etc.)
+ - Any potential mitigations you've already identified
+5. Allow up to 7 days for an initial response.
+ You should receive an acknowledgment of your report and an estimated timeline for a fix.
+6. (Optional) If you have a fix and would like to contribute your patch, please work
+ directly with the maintainers via `cobra-security@googlegroups.com` to
+ coordinate pushing the patch to GitHub, cutting a new release, and disclosing the change.
+
+## Response Process
+
+When a security vulnerability report is received, the `cobra` maintainers will:
+
+1. Confirm receipt of the vulnerability report within 7 days.
+2. Assess the report to determine if it constitutes a security vulnerability.
+3. If confirmed, assign the vulnerability a severity level and create a timeline for addressing it.
+4. Develop and test a fix.
+5. Patch the vulnerability and make a new GitHub release: the maintainers will coordinate disclosure with the reporter.
+6. Create a new GitHub Security Advisory to inform the broader Go ecosystem
+
+## Disclosure Policy
+
+The `cobra` maintainers follow a coordinated disclosure process:
+
+1. Security vulnerabilities will be addressed as quickly as possible.
+2. A CVE (Common Vulnerabilities and Exposures) identifier will be requested for significant vulnerabilities
+ that are within `cobra` itself.
+3. Once a fix is ready, the maintainers will:
+ - Release a new version containing the fix.
+ - Update the security advisory with details about the vulnerability.
+ - Credit the reporter (unless they wish to remain anonymous).
+ - Credit the fixer (unless they wish to remain anonymous, this may be the same as the reporter).
+ - Announce the vulnerability through appropriate channels
+ (GitHub Security Advisory, mailing lists, GitHub Releases, etc.)
+
+## Supported Versions
+
+Security fixes will typically only be released for the most recent major release.
+
+## Upstream Security Issues
+
+`cobra` generally will not accept vulnerability reports that originate in upstream
+dependencies. I.e., if there is a problem in Go code that `cobra` depends on,
+it is best to engage that project's maintainers and owners.
+
+This security policy primarily pertains only to `cobra` itself but if you believe you've
+identified a problem that originates in an upstream dependency and is being widely
+distributed by `cobra`, please follow the disclosure procedure above: the `cobra`
+maintainers will work with you to determine the severity and ecosystem impact.
+
+## Security Updates and CVEs
+
+Information about known security vulnerabilities and CVEs affecting `cobra` will
+be published as GitHub Security Advisories at
+https://github.com/spf13/cobra/security/advisories.
+
+All users are encouraged to watch the repository and upgrade promptly when
+security releases are published.
+
+## `cobra` Security Best Practices for Users
+
+When using `cobra` in your CLIs, the `cobra` maintainers recommend the following:
+
+1. Always use the latest version of `cobra`.
+2. [Use Go modules](https://go.dev/blog/using-go-modules) for dependency management.
+3. Always use the latest possible version of Go.
+
+## Security Best Practices for Contributors
+
+When contributing to `cobra`:
+
+1. Be mindful of security implications when adding new features or modifying existing ones.
+2. Be aware of `cobra`'s extremely large reach: it is used in nearly every Go CLI
+ (like Kubernetes, Docker, Prometheus, etc. etc.)
+3. Write tests that explicitly cover edge cases and potential issues.
+4. If you discover a security issue while working on `cobra`, please report it
+ following the process above rather than opening a public pull request or issue that
+ addresses the vulnerability.
+5. Take personal sec-ops seriously and secure your GitHub account: use [two-factor authentication](https://docs.github.com/en/authentication/securing-your-account-with-two-factor-authentication-2fa),
+ [sign your commits with a GPG or SSH key](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification),
+ etc.
+
+## Acknowledgments
+
+The `cobra` maintainers would like to thank all security researchers and
+community members who help keep cobra, its users, and the entire Go ecosystem secure through responsible disclosures!!
+
+---
+
+*This security policy is inspired by the [Open Web Application Security Project (OWASP)](https://owasp.org/) guidelines and security best practices.*
diff --git a/vendor/github.com/spf13/cobra/command.go b/vendor/github.com/spf13/cobra/command.go
index dbb2c298ba..78088db69c 100644
--- a/vendor/github.com/spf13/cobra/command.go
+++ b/vendor/github.com/spf13/cobra/command.go
@@ -39,7 +39,7 @@ const (
)
// FParseErrWhitelist configures Flag parse errors to be ignored
-type FParseErrWhitelist flag.ParseErrorsWhitelist
+type FParseErrWhitelist flag.ParseErrorsAllowlist
// Group Structure to manage groups for commands
type Group struct {
@@ -1296,6 +1296,11 @@ Simply type ` + c.DisplayName() + ` help [path to command] for full details.`,
c.Printf("Unknown help topic %#q\n", args)
CheckErr(c.Root().Usage())
} else {
+ // FLow the context down to be used in help text
+ if cmd.ctx == nil {
+ cmd.ctx = c.ctx
+ }
+
cmd.InitDefaultHelpFlag() // make possible 'help' flag to be shown
cmd.InitDefaultVersionFlag() // make possible 'version' flag to be shown
CheckErr(cmd.Help())
@@ -1872,7 +1877,7 @@ func (c *Command) ParseFlags(args []string) error {
c.mergePersistentFlags()
// do it here after merging all flags and just before parse
- c.Flags().ParseErrorsWhitelist = flag.ParseErrorsWhitelist(c.FParseErrWhitelist)
+ c.Flags().ParseErrorsAllowlist = flag.ParseErrorsAllowlist(c.FParseErrWhitelist)
err := c.Flags().Parse(args)
// Print warnings if they occurred (e.g. deprecated flag messages).
@@ -2020,7 +2025,7 @@ func defaultUsageFunc(w io.Writer, in interface{}) error {
fmt.Fprint(w, trimRightSpace(c.InheritedFlags().FlagUsages()))
}
if c.HasHelpSubCommands() {
- fmt.Fprintf(w, "\n\nAdditional help topcis:")
+ fmt.Fprintf(w, "\n\nAdditional help topics:")
for _, subcmd := range c.Commands() {
if subcmd.IsAdditionalHelpTopicCommand() {
fmt.Fprintf(w, "\n %s %s", rpad(subcmd.CommandPath(), subcmd.CommandPathPadding()), subcmd.Short)
diff --git a/vendor/github.com/spf13/cobra/completions.go b/vendor/github.com/spf13/cobra/completions.go
index a1752f7631..d3607c2d2f 100644
--- a/vendor/github.com/spf13/cobra/completions.go
+++ b/vendor/github.com/spf13/cobra/completions.go
@@ -115,6 +115,13 @@ type CompletionOptions struct {
DisableDescriptions bool
// HiddenDefaultCmd makes the default 'completion' command hidden
HiddenDefaultCmd bool
+ // DefaultShellCompDirective sets the ShellCompDirective that is returned
+ // if no special directive can be determined
+ DefaultShellCompDirective *ShellCompDirective
+}
+
+func (receiver *CompletionOptions) SetDefaultShellCompDirective(directive ShellCompDirective) {
+ receiver.DefaultShellCompDirective = &directive
}
// Completion is a string that can be used for completions
@@ -375,7 +382,7 @@ func (c *Command) getCompletions(args []string) (*Command, []Completion, ShellCo
// Error while attempting to parse flags
if flagErr != nil {
// If error type is flagCompError and we don't want flagCompletion we should ignore the error
- if _, ok := flagErr.(*flagCompError); !(ok && !flagCompletion) {
+ if _, ok := flagErr.(*flagCompError); !ok || flagCompletion {
return finalCmd, []Completion{}, ShellCompDirectiveDefault, flagErr
}
}
@@ -480,6 +487,14 @@ func (c *Command) getCompletions(args []string) (*Command, []Completion, ShellCo
}
} else {
directive = ShellCompDirectiveDefault
+ // check current and parent commands for a custom DefaultShellCompDirective
+ for cmd := finalCmd; cmd != nil; cmd = cmd.parent {
+ if cmd.CompletionOptions.DefaultShellCompDirective != nil {
+ directive = *cmd.CompletionOptions.DefaultShellCompDirective
+ break
+ }
+ }
+
if flag == nil {
foundLocalNonPersistentFlag := false
// If TraverseChildren is true on the root command we don't check for
@@ -773,7 +788,7 @@ See each sub-command's help for details on how to use the generated script.
// shell completion for it (prog __complete completion '')
subCmd, cmdArgs, err := c.Find(args)
if err != nil || subCmd.Name() != compCmdName &&
- !(subCmd.Name() == ShellCompRequestCmd && len(cmdArgs) > 1 && cmdArgs[0] == compCmdName) {
+ (subCmd.Name() != ShellCompRequestCmd || len(cmdArgs) <= 1 || cmdArgs[0] != compCmdName) {
// The completion command is not being called or being completed so we remove it.
c.RemoveCommand(completionCmd)
return
diff --git a/vendor/go.etcd.io/etcd/api/v3/version/version.go b/vendor/go.etcd.io/etcd/api/v3/version/version.go
index d77e31a972..9e7bc64c17 100644
--- a/vendor/go.etcd.io/etcd/api/v3/version/version.go
+++ b/vendor/go.etcd.io/etcd/api/v3/version/version.go
@@ -26,7 +26,7 @@ import (
var (
// MinClusterVersion is the min cluster version this etcd binary is compatible with.
MinClusterVersion = "3.0.0"
- Version = "3.6.4"
+ Version = "3.6.5"
APIVersion = "unknown"
// Git SHA Value will be set during build
diff --git a/vendor/go.etcd.io/etcd/client/v3/retry_interceptor.go b/vendor/go.etcd.io/etcd/client/v3/retry_interceptor.go
index 2b9301a580..7703e673b0 100644
--- a/vendor/go.etcd.io/etcd/client/v3/retry_interceptor.go
+++ b/vendor/go.etcd.io/etcd/client/v3/retry_interceptor.go
@@ -351,11 +351,11 @@ func isContextError(err error) bool {
func contextErrToGRPCErr(err error) error {
switch {
case errors.Is(err, context.DeadlineExceeded):
- return status.Errorf(codes.DeadlineExceeded, err.Error())
+ return status.Error(codes.DeadlineExceeded, err.Error())
case errors.Is(err, context.Canceled):
- return status.Errorf(codes.Canceled, err.Error())
+ return status.Error(codes.Canceled, err.Error())
default:
- return status.Errorf(codes.Unknown, err.Error())
+ return status.Error(codes.Unknown, err.Error())
}
}
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/config.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/config.go
index a01bfafbe0..6bd50d4c9b 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/config.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/config.go
@@ -176,6 +176,10 @@ func WithMessageEvents(events ...event) Option {
// WithSpanNameFormatter takes a function that will be called on every
// request and the returned string will become the Span Name.
+//
+// When using [http.ServeMux] (or any middleware that sets the Pattern of [http.Request]),
+// the span name formatter will run twice. Once when the span is created, and
+// second time after the middleware, so the pattern can be used.
func WithSpanNameFormatter(f func(operation string, r *http.Request) string) Option {
return optionFunc(func(c *config) {
c.SpanNameFormatter = f
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go
index 3ea05d0199..937f9b4e73 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go
@@ -98,7 +98,7 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http
ctx := h.propagators.Extract(r.Context(), propagation.HeaderCarrier(r.Header))
opts := []trace.SpanStartOption{
- trace.WithAttributes(h.semconv.RequestTraceAttrs(h.server, r)...),
+ trace.WithAttributes(h.semconv.RequestTraceAttrs(h.server, r, semconv.RequestTraceAttrsOpts{})...),
}
opts = append(opts, h.spanStartOptions...)
@@ -176,7 +176,12 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http
ctx = ContextWithLabeler(ctx, labeler)
}
- next.ServeHTTP(w, r.WithContext(ctx))
+ r = r.WithContext(ctx)
+ next.ServeHTTP(w, r)
+
+ if r.Pattern != "" {
+ span.SetName(h.spanNameFormatter(h.operation, r))
+ }
statusCode := rww.StatusCode()
bytesWritten := rww.BytesWritten()
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/body_wrapper.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/body_wrapper.go
index a945f55661..d032aa841b 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/body_wrapper.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/body_wrapper.go
@@ -1,6 +1,11 @@
+// Code generated by gotmpl. DO NOT MODIFY.
+// source: internal/shared/request/body_wrapper.go.tmpl
+
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
+// Package request provides types and functionality to handle HTTP request
+// handling.
package request // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request"
import (
@@ -53,7 +58,7 @@ func (w *BodyWrapper) updateReadData(n int64, err error) {
}
}
-// Closes closes the io.ReadCloser.
+// Close closes the io.ReadCloser.
func (w *BodyWrapper) Close() error {
return w.ReadCloser.Close()
}
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/gen.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/gen.go
new file mode 100644
index 0000000000..9e00dd2fce
--- /dev/null
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/gen.go
@@ -0,0 +1,10 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+package request // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request"
+
+// Generate request package:
+//go:generate gotmpl --body=../../../../../../internal/shared/request/body_wrapper.go.tmpl "--data={}" --out=body_wrapper.go
+//go:generate gotmpl --body=../../../../../../internal/shared/request/body_wrapper_test.go.tmpl "--data={}" --out=body_wrapper_test.go
+//go:generate gotmpl --body=../../../../../../internal/shared/request/resp_writer_wrapper.go.tmpl "--data={}" --out=resp_writer_wrapper.go
+//go:generate gotmpl --body=../../../../../../internal/shared/request/resp_writer_wrapper_test.go.tmpl "--data={}" --out=resp_writer_wrapper_test.go
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/resp_writer_wrapper.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/resp_writer_wrapper.go
index fbc344cbdd..ca2e4c14c7 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/resp_writer_wrapper.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/resp_writer_wrapper.go
@@ -1,3 +1,6 @@
+// Code generated by gotmpl. DO NOT MODIFY.
+// source: internal/shared/request/resp_writer_wrapper.go.tmpl
+
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
@@ -102,7 +105,7 @@ func (w *RespWriterWrapper) BytesWritten() int64 {
return w.written
}
-// BytesWritten returns the HTTP status code that was sent.
+// StatusCode returns the HTTP status code that was sent.
func (w *RespWriterWrapper) StatusCode() int {
w.mu.RLock()
defer w.mu.RUnlock()
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/env.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/env.go
index eaf4c37967..7cb9693d98 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/env.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/env.go
@@ -1,4 +1,4 @@
-// Code created by gotmpl. DO NOT MODIFY.
+// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/semconv/env.go.tmpl
// Copyright The OpenTelemetry Authors
@@ -20,7 +20,7 @@ import (
)
// OTelSemConvStabilityOptIn is an environment variable.
-// That can be set to "old" or "http/dup" to opt into the new HTTP semantic conventions.
+// That can be set to "http/dup" to keep getting the old HTTP semantic conventions.
const OTelSemConvStabilityOptIn = "OTEL_SEMCONV_STABILITY_OPT_IN"
type ResponseTelemetry struct {
@@ -61,26 +61,40 @@ type HTTPServer struct {
//
// If the primary server name is not known, server should be an empty string.
// The req Host will be used to determine the server instead.
-func (s HTTPServer) RequestTraceAttrs(server string, req *http.Request) []attribute.KeyValue {
+func (s HTTPServer) RequestTraceAttrs(server string, req *http.Request, opts RequestTraceAttrsOpts) []attribute.KeyValue {
+ attrs := CurrentHTTPServer{}.RequestTraceAttrs(server, req, opts)
if s.duplicate {
- return append(OldHTTPServer{}.RequestTraceAttrs(server, req), CurrentHTTPServer{}.RequestTraceAttrs(server, req)...)
+ return OldHTTPServer{}.RequestTraceAttrs(server, req, attrs)
+ }
+ return attrs
+}
+
+func (s HTTPServer) NetworkTransportAttr(network string) []attribute.KeyValue {
+ if s.duplicate {
+ return []attribute.KeyValue{
+ OldHTTPServer{}.NetworkTransportAttr(network),
+ CurrentHTTPServer{}.NetworkTransportAttr(network),
+ }
+ }
+ return []attribute.KeyValue{
+ CurrentHTTPServer{}.NetworkTransportAttr(network),
}
- return OldHTTPServer{}.RequestTraceAttrs(server, req)
}
// ResponseTraceAttrs returns trace attributes for telemetry from an HTTP response.
//
// If any of the fields in the ResponseTelemetry are not set the attribute will be omitted.
func (s HTTPServer) ResponseTraceAttrs(resp ResponseTelemetry) []attribute.KeyValue {
+ attrs := CurrentHTTPServer{}.ResponseTraceAttrs(resp)
if s.duplicate {
- return append(OldHTTPServer{}.ResponseTraceAttrs(resp), CurrentHTTPServer{}.ResponseTraceAttrs(resp)...)
+ return OldHTTPServer{}.ResponseTraceAttrs(resp, attrs)
}
- return OldHTTPServer{}.ResponseTraceAttrs(resp)
+ return attrs
}
// Route returns the attribute for the route.
func (s HTTPServer) Route(route string) attribute.KeyValue {
- return OldHTTPServer{}.Route(route)
+ return CurrentHTTPServer{}.Route(route)
}
// Status returns a span status code and message for an HTTP status code
@@ -112,6 +126,8 @@ type MetricAttributes struct {
type MetricData struct {
RequestSize int64
+
+ // The request duration, in milliseconds
ElapsedTime float64
}
@@ -130,7 +146,19 @@ var (
)
func (s HTTPServer) RecordMetrics(ctx context.Context, md ServerMetricData) {
- if s.requestBytesCounter != nil && s.responseBytesCounter != nil && s.serverLatencyMeasure != nil {
+ if s.requestDurationHistogram != nil && s.requestBodySizeHistogram != nil && s.responseBodySizeHistogram != nil {
+ attributes := CurrentHTTPServer{}.MetricAttributes(md.ServerName, md.Req, md.StatusCode, md.AdditionalAttributes)
+ o := metric.WithAttributeSet(attribute.NewSet(attributes...))
+ recordOpts := metricRecordOptionPool.Get().(*[]metric.RecordOption)
+ *recordOpts = append(*recordOpts, o)
+ s.requestBodySizeHistogram.Record(ctx, md.RequestSize, *recordOpts...)
+ s.responseBodySizeHistogram.Record(ctx, md.ResponseSize, *recordOpts...)
+ s.requestDurationHistogram.Record(ctx, md.ElapsedTime/1000.0, o)
+ *recordOpts = (*recordOpts)[:0]
+ metricRecordOptionPool.Put(recordOpts)
+ }
+
+ if s.duplicate && s.requestBytesCounter != nil && s.responseBytesCounter != nil && s.serverLatencyMeasure != nil {
attributes := OldHTTPServer{}.MetricAttributes(md.ServerName, md.Req, md.StatusCode, md.AdditionalAttributes)
o := metric.WithAttributeSet(attribute.NewSet(attributes...))
addOpts := metricAddOptionPool.Get().(*[]metric.AddOption)
@@ -141,29 +169,28 @@ func (s HTTPServer) RecordMetrics(ctx context.Context, md ServerMetricData) {
*addOpts = (*addOpts)[:0]
metricAddOptionPool.Put(addOpts)
}
+}
- if s.duplicate && s.requestDurationHistogram != nil && s.requestBodySizeHistogram != nil && s.responseBodySizeHistogram != nil {
- attributes := CurrentHTTPServer{}.MetricAttributes(md.ServerName, md.Req, md.StatusCode, md.AdditionalAttributes)
- o := metric.WithAttributeSet(attribute.NewSet(attributes...))
- recordOpts := metricRecordOptionPool.Get().(*[]metric.RecordOption)
- *recordOpts = append(*recordOpts, o)
- s.requestBodySizeHistogram.Record(ctx, md.RequestSize, *recordOpts...)
- s.responseBodySizeHistogram.Record(ctx, md.ResponseSize, *recordOpts...)
- s.requestDurationHistogram.Record(ctx, md.ElapsedTime, o)
- *recordOpts = (*recordOpts)[:0]
- metricRecordOptionPool.Put(recordOpts)
+// hasOptIn returns true if the comma-separated version string contains the
+// exact optIn value.
+func hasOptIn(version, optIn string) bool {
+ for _, v := range strings.Split(version, ",") {
+ if strings.TrimSpace(v) == optIn {
+ return true
+ }
}
+ return false
}
func NewHTTPServer(meter metric.Meter) HTTPServer {
env := strings.ToLower(os.Getenv(OTelSemConvStabilityOptIn))
- duplicate := env == "http/dup"
+ duplicate := hasOptIn(env, "http/dup")
server := HTTPServer{
duplicate: duplicate,
}
- server.requestBytesCounter, server.responseBytesCounter, server.serverLatencyMeasure = OldHTTPServer{}.createMeasures(meter)
+ server.requestBodySizeHistogram, server.responseBodySizeHistogram, server.requestDurationHistogram = CurrentHTTPServer{}.createMeasures(meter)
if duplicate {
- server.requestBodySizeHistogram, server.responseBodySizeHistogram, server.requestDurationHistogram = CurrentHTTPServer{}.createMeasures(meter)
+ server.requestBytesCounter, server.responseBytesCounter, server.serverLatencyMeasure = OldHTTPServer{}.createMeasures(meter)
}
return server
}
@@ -183,13 +210,13 @@ type HTTPClient struct {
func NewHTTPClient(meter metric.Meter) HTTPClient {
env := strings.ToLower(os.Getenv(OTelSemConvStabilityOptIn))
- duplicate := env == "http/dup"
+ duplicate := hasOptIn(env, "http/dup")
client := HTTPClient{
duplicate: duplicate,
}
- client.requestBytesCounter, client.responseBytesCounter, client.latencyMeasure = OldHTTPClient{}.createMeasures(meter)
+ client.requestBodySize, client.requestDuration = CurrentHTTPClient{}.createMeasures(meter)
if duplicate {
- client.requestBodySize, client.requestDuration = CurrentHTTPClient{}.createMeasures(meter)
+ client.requestBytesCounter, client.responseBytesCounter, client.latencyMeasure = OldHTTPClient{}.createMeasures(meter)
}
return client
@@ -197,19 +224,20 @@ func NewHTTPClient(meter metric.Meter) HTTPClient {
// RequestTraceAttrs returns attributes for an HTTP request made by a client.
func (c HTTPClient) RequestTraceAttrs(req *http.Request) []attribute.KeyValue {
+ attrs := CurrentHTTPClient{}.RequestTraceAttrs(req)
if c.duplicate {
- return append(OldHTTPClient{}.RequestTraceAttrs(req), CurrentHTTPClient{}.RequestTraceAttrs(req)...)
+ return OldHTTPClient{}.RequestTraceAttrs(req, attrs)
}
- return OldHTTPClient{}.RequestTraceAttrs(req)
+ return attrs
}
// ResponseTraceAttrs returns metric attributes for an HTTP request made by a client.
func (c HTTPClient) ResponseTraceAttrs(resp *http.Response) []attribute.KeyValue {
+ attrs := CurrentHTTPClient{}.ResponseTraceAttrs(resp)
if c.duplicate {
- return append(OldHTTPClient{}.ResponseTraceAttrs(resp), CurrentHTTPClient{}.ResponseTraceAttrs(resp)...)
+ return OldHTTPClient{}.ResponseTraceAttrs(resp, attrs)
}
-
- return OldHTTPClient{}.ResponseTraceAttrs(resp)
+ return attrs
}
func (c HTTPClient) Status(code int) (codes.Code, string) {
@@ -223,11 +251,7 @@ func (c HTTPClient) Status(code int) (codes.Code, string) {
}
func (c HTTPClient) ErrorType(err error) attribute.KeyValue {
- if c.duplicate {
- return CurrentHTTPClient{}.ErrorType(err)
- }
-
- return attribute.KeyValue{}
+ return CurrentHTTPClient{}.ErrorType(err)
}
type MetricOpts struct {
@@ -246,17 +270,17 @@ func (o MetricOpts) AddOptions() metric.AddOption {
func (c HTTPClient) MetricOptions(ma MetricAttributes) map[string]MetricOpts {
opts := map[string]MetricOpts{}
- attributes := OldHTTPClient{}.MetricAttributes(ma.Req, ma.StatusCode, ma.AdditionalAttributes)
+ attributes := CurrentHTTPClient{}.MetricAttributes(ma.Req, ma.StatusCode, ma.AdditionalAttributes)
set := metric.WithAttributeSet(attribute.NewSet(attributes...))
- opts["old"] = MetricOpts{
+ opts["new"] = MetricOpts{
measurement: set,
addOptions: set,
}
if c.duplicate {
- attributes := CurrentHTTPClient{}.MetricAttributes(ma.Req, ma.StatusCode, ma.AdditionalAttributes)
+ attributes := OldHTTPClient{}.MetricAttributes(ma.Req, ma.StatusCode, ma.AdditionalAttributes)
set := metric.WithAttributeSet(attribute.NewSet(attributes...))
- opts["new"] = MetricOpts{
+ opts["old"] = MetricOpts{
measurement: set,
addOptions: set,
}
@@ -266,17 +290,17 @@ func (c HTTPClient) MetricOptions(ma MetricAttributes) map[string]MetricOpts {
}
func (s HTTPClient) RecordMetrics(ctx context.Context, md MetricData, opts map[string]MetricOpts) {
- if s.requestBytesCounter == nil || s.latencyMeasure == nil {
+ if s.requestBodySize == nil || s.requestDuration == nil {
// This will happen if an HTTPClient{} is used instead of NewHTTPClient().
return
}
- s.requestBytesCounter.Add(ctx, md.RequestSize, opts["old"].AddOptions())
- s.latencyMeasure.Record(ctx, md.ElapsedTime, opts["old"].MeasurementOption())
+ s.requestBodySize.Record(ctx, md.RequestSize, opts["new"].MeasurementOption())
+ s.requestDuration.Record(ctx, md.ElapsedTime/1000, opts["new"].MeasurementOption())
if s.duplicate {
- s.requestBodySize.Record(ctx, md.RequestSize, opts["new"].MeasurementOption())
- s.requestDuration.Record(ctx, md.ElapsedTime, opts["new"].MeasurementOption())
+ s.requestBytesCounter.Add(ctx, md.RequestSize, opts["old"].AddOptions())
+ s.latencyMeasure.Record(ctx, md.ElapsedTime, opts["old"].MeasurementOption())
}
}
@@ -288,3 +312,12 @@ func (s HTTPClient) RecordResponseSize(ctx context.Context, responseData int64,
s.responseBytesCounter.Add(ctx, responseData, opts["old"].AddOptions())
}
+
+func (s HTTPClient) TraceAttributes(host string) []attribute.KeyValue {
+ attrs := CurrentHTTPClient{}.TraceAttributes(host)
+ if s.duplicate {
+ return OldHTTPClient{}.TraceAttributes(host, attrs)
+ }
+
+ return attrs
+}
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/gen.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/gen.go
index 32630864bf..f2cf8a152d 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/gen.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/gen.go
@@ -4,11 +4,11 @@
package semconv // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv"
// Generate semconv package:
-//go:generate gotmpl --body=../../../../../../internal/shared/semconv/bench_test.go.tmpl "--data={}" --out=bench_test.go
-//go:generate gotmpl --body=../../../../../../internal/shared/semconv/env.go.tmpl "--data={}" --out=env.go
-//go:generate gotmpl --body=../../../../../../internal/shared/semconv/env_test.go.tmpl "--data={}" --out=env_test.go
-//go:generate gotmpl --body=../../../../../../internal/shared/semconv/httpconv.go.tmpl "--data={}" --out=httpconv.go
-//go:generate gotmpl --body=../../../../../../internal/shared/semconv/httpconv_test.go.tmpl "--data={}" --out=httpconv_test.go
-//go:generate gotmpl --body=../../../../../../internal/shared/semconv/util.go.tmpl "--data={}" --out=util.go
-//go:generate gotmpl --body=../../../../../../internal/shared/semconv/util_test.go.tmpl "--data={}" --out=util_test.go
-//go:generate gotmpl --body=../../../../../../internal/shared/semconv/v1.20.0.go.tmpl "--data={}" --out=v1.20.0.go
+//go:generate gotmpl --body=../../../../../../internal/shared/semconv/bench_test.go.tmpl "--data={ \"pkg\": \"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp\" }" --out=bench_test.go
+//go:generate gotmpl --body=../../../../../../internal/shared/semconv/env.go.tmpl "--data={ \"pkg\": \"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp\" }" --out=env.go
+//go:generate gotmpl --body=../../../../../../internal/shared/semconv/env_test.go.tmpl "--data={ \"pkg\": \"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp\" }" --out=env_test.go
+//go:generate gotmpl --body=../../../../../../internal/shared/semconv/httpconv.go.tmpl "--data={ \"pkg\": \"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp\" }" --out=httpconv.go
+//go:generate gotmpl --body=../../../../../../internal/shared/semconv/httpconv_test.go.tmpl "--data={ \"pkg\": \"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp\" }" --out=httpconv_test.go
+//go:generate gotmpl --body=../../../../../../internal/shared/semconv/util.go.tmpl "--data={ \"pkg\": \"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp\" }" --out=util.go
+//go:generate gotmpl --body=../../../../../../internal/shared/semconv/util_test.go.tmpl "--data={ \"pkg\": \"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp\" }" --out=util_test.go
+//go:generate gotmpl --body=../../../../../../internal/shared/semconv/v1.20.0.go.tmpl "--data={ \"pkg\": \"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp\" }" --out=v1.20.0.go
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/httpconv.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/httpconv.go
index 8c3c627513..53976b0d5a 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/httpconv.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/httpconv.go
@@ -1,9 +1,11 @@
-// Code created by gotmpl. DO NOT MODIFY.
+// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/semconv/httpconv.go.tmpl
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
+// Package semconv provides OpenTelemetry semantic convention types and
+// functionality.
package semconv // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv"
import (
@@ -20,9 +22,14 @@ import (
semconvNew "go.opentelemetry.io/otel/semconv/v1.26.0"
)
+type RequestTraceAttrsOpts struct {
+ // If set, this is used as value for the "http.client_ip" attribute.
+ HTTPClientIP string
+}
+
type CurrentHTTPServer struct{}
-// TraceRequest returns trace attributes for an HTTP request received by a
+// RequestTraceAttrs returns trace attributes for an HTTP request received by a
// server.
//
// The server must be the primary server name if it is known. For example this
@@ -38,7 +45,7 @@ type CurrentHTTPServer struct{}
//
// If the primary server name is not known, server should be an empty string.
// The req Host will be used to determine the server instead.
-func (n CurrentHTTPServer) RequestTraceAttrs(server string, req *http.Request) []attribute.KeyValue {
+func (n CurrentHTTPServer) RequestTraceAttrs(server string, req *http.Request, opts RequestTraceAttrsOpts) []attribute.KeyValue {
count := 3 // ServerAddress, Method, Scheme
var host string
@@ -65,7 +72,8 @@ func (n CurrentHTTPServer) RequestTraceAttrs(server string, req *http.Request) [
scheme := n.scheme(req.TLS != nil)
- if peer, peerPort := SplitHostPort(req.RemoteAddr); peer != "" {
+ peer, peerPort := SplitHostPort(req.RemoteAddr)
+ if peer != "" {
// The Go HTTP server sets RemoteAddr to "IP:port", this will not be a
// file-path that would be interpreted with a sock family.
count++
@@ -79,7 +87,17 @@ func (n CurrentHTTPServer) RequestTraceAttrs(server string, req *http.Request) [
count++
}
- clientIP := serverClientIP(req.Header.Get("X-Forwarded-For"))
+ // For client IP, use, in order:
+ // 1. The value passed in the options
+ // 2. The value in the X-Forwarded-For header
+ // 3. The peer address
+ clientIP := opts.HTTPClientIP
+ if clientIP == "" {
+ clientIP = serverClientIP(req.Header.Get("X-Forwarded-For"))
+ if clientIP == "" {
+ clientIP = peer
+ }
+ }
if clientIP != "" {
count++
}
@@ -96,6 +114,11 @@ func (n CurrentHTTPServer) RequestTraceAttrs(server string, req *http.Request) [
count++
}
+ route := httpRoute(req.Pattern)
+ if route != "" {
+ count++
+ }
+
attrs := make([]attribute.KeyValue, 0, count)
attrs = append(attrs,
semconvNew.ServerAddress(host),
@@ -119,7 +142,7 @@ func (n CurrentHTTPServer) RequestTraceAttrs(server string, req *http.Request) [
}
}
- if useragent := req.UserAgent(); useragent != "" {
+ if useragent != "" {
attrs = append(attrs, semconvNew.UserAgentOriginal(useragent))
}
@@ -138,9 +161,26 @@ func (n CurrentHTTPServer) RequestTraceAttrs(server string, req *http.Request) [
attrs = append(attrs, semconvNew.NetworkProtocolVersion(protoVersion))
}
+ if route != "" {
+ attrs = append(attrs, n.Route(route))
+ }
+
return attrs
}
+func (n CurrentHTTPServer) NetworkTransportAttr(network string) attribute.KeyValue {
+ switch network {
+ case "tcp", "tcp4", "tcp6":
+ return semconvNew.NetworkTransportTCP
+ case "udp", "udp4", "udp6":
+ return semconvNew.NetworkTransportUDP
+ case "unix", "unixgram", "unixpacket":
+ return semconvNew.NetworkTransportUnix
+ default:
+ return semconvNew.NetworkTransportPipe
+ }
+}
+
func (n CurrentHTTPServer) method(method string) (attribute.KeyValue, attribute.KeyValue) {
if method == "" {
return semconvNew.HTTPRequestMethodGet, attribute.KeyValue{}
@@ -163,9 +203,11 @@ func (n CurrentHTTPServer) scheme(https bool) attribute.KeyValue { // nolint:rev
return semconvNew.URLScheme("http")
}
-// TraceResponse returns trace attributes for telemetry from an HTTP response.
+// ResponseTraceAttrs returns trace attributes for telemetry from an HTTP
+// response.
//
-// If any of the fields in the ResponseTelemetry are not set the attribute will be omitted.
+// If any of the fields in the ResponseTelemetry are not set the attribute will
+// be omitted.
func (n CurrentHTTPServer) ResponseTraceAttrs(resp ResponseTelemetry) []attribute.KeyValue {
var count int
@@ -228,6 +270,7 @@ func (n CurrentHTTPServer) createMeasures(meter metric.Meter) (metric.Int64Histo
semconvNew.HTTPServerRequestDurationName,
metric.WithUnit(semconvNew.HTTPServerRequestDurationUnit),
metric.WithDescription(semconvNew.HTTPServerRequestDurationDescription),
+ metric.WithExplicitBucketBoundaries(0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10),
)
handleErr(err)
@@ -446,6 +489,7 @@ func (n CurrentHTTPClient) createMeasures(meter metric.Meter) (metric.Int64Histo
semconvNew.HTTPClientRequestDurationName,
metric.WithUnit(semconvNew.HTTPClientRequestDurationUnit),
metric.WithDescription(semconvNew.HTTPClientRequestDurationDescription),
+ metric.WithExplicitBucketBoundaries(0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10),
)
handleErr(err)
@@ -488,7 +532,7 @@ func (n CurrentHTTPClient) MetricAttributes(req *http.Request, statusCode int, a
attributes = append(attributes,
semconvNew.HTTPRequestMethodKey.String(standardizeHTTPMethod(req.Method)),
semconvNew.ServerAddress(requestHost),
- n.scheme(req.TLS != nil),
+ n.scheme(req),
)
if port > 0 {
@@ -507,8 +551,18 @@ func (n CurrentHTTPClient) MetricAttributes(req *http.Request, statusCode int, a
return attributes
}
-func (n CurrentHTTPClient) scheme(https bool) attribute.KeyValue { // nolint:revive
- if https {
+// TraceAttributes returns attributes for httptrace.
+func (n CurrentHTTPClient) TraceAttributes(host string) []attribute.KeyValue {
+ return []attribute.KeyValue{
+ semconvNew.ServerAddress(host),
+ }
+}
+
+func (n CurrentHTTPClient) scheme(req *http.Request) attribute.KeyValue {
+ if req.URL != nil && req.URL.Scheme != "" {
+ return semconvNew.URLScheme(req.URL.Scheme)
+ }
+ if req.TLS != nil {
return semconvNew.URLScheme("https")
}
return semconvNew.URLScheme("http")
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/util.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/util.go
index 558efd0594..bc1f7751db 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/util.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/util.go
@@ -1,4 +1,4 @@
-// Code created by gotmpl. DO NOT MODIFY.
+// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/semconv/util.go.tmpl
// Copyright The OpenTelemetry Authors
@@ -28,17 +28,17 @@ func SplitHostPort(hostport string) (host string, port int) {
port = -1
if strings.HasPrefix(hostport, "[") {
- addrEnd := strings.LastIndex(hostport, "]")
+ addrEnd := strings.LastIndexByte(hostport, ']')
if addrEnd < 0 {
// Invalid hostport.
return
}
- if i := strings.LastIndex(hostport[addrEnd:], ":"); i < 0 {
+ if i := strings.LastIndexByte(hostport[addrEnd:], ':'); i < 0 {
host = hostport[1:addrEnd]
return
}
} else {
- if i := strings.LastIndex(hostport, ":"); i < 0 {
+ if i := strings.LastIndexByte(hostport, ':'); i < 0 {
host = hostport
return
}
@@ -70,15 +70,31 @@ func requiredHTTPPort(https bool, port int) int { // nolint:revive
}
func serverClientIP(xForwardedFor string) string {
- if idx := strings.Index(xForwardedFor, ","); idx >= 0 {
+ if idx := strings.IndexByte(xForwardedFor, ','); idx >= 0 {
xForwardedFor = xForwardedFor[:idx]
}
return xForwardedFor
}
+func httpRoute(pattern string) string {
+ if idx := strings.IndexByte(pattern, '/'); idx >= 0 {
+ return pattern[idx:]
+ }
+ return ""
+}
+
func netProtocol(proto string) (name string, version string) {
name, version, _ = strings.Cut(proto, "/")
- name = strings.ToLower(name)
+ switch name {
+ case "HTTP":
+ name = "http"
+ case "QUIC":
+ name = "quic"
+ case "SPDY":
+ name = "spdy"
+ default:
+ name = strings.ToLower(name)
+ }
return name, version
}
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/v1.20.0.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/v1.20.0.go
index 57d1507b62..ba7fccf1ef 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/v1.20.0.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/v1.20.0.go
@@ -1,4 +1,4 @@
-// Code created by gotmpl. DO NOT MODIFY.
+// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/semconv/v120.0.go.tmpl
// Copyright The OpenTelemetry Authors
@@ -37,16 +37,18 @@ type OldHTTPServer struct{}
//
// If the primary server name is not known, server should be an empty string.
// The req Host will be used to determine the server instead.
-func (o OldHTTPServer) RequestTraceAttrs(server string, req *http.Request) []attribute.KeyValue {
- return semconvutil.HTTPServerRequest(server, req)
+func (o OldHTTPServer) RequestTraceAttrs(server string, req *http.Request, attrs []attribute.KeyValue) []attribute.KeyValue {
+ return semconvutil.HTTPServerRequest(server, req, semconvutil.HTTPServerRequestOptions{}, attrs)
+}
+
+func (o OldHTTPServer) NetworkTransportAttr(network string) attribute.KeyValue {
+ return semconvutil.NetTransport(network)
}
// ResponseTraceAttrs returns trace attributes for telemetry from an HTTP response.
//
// If any of the fields in the ResponseTelemetry are not set the attribute will be omitted.
-func (o OldHTTPServer) ResponseTraceAttrs(resp ResponseTelemetry) []attribute.KeyValue {
- attributes := []attribute.KeyValue{}
-
+func (o OldHTTPServer) ResponseTraceAttrs(resp ResponseTelemetry, attributes []attribute.KeyValue) []attribute.KeyValue {
if resp.ReadBytes > 0 {
attributes = append(attributes, semconv.HTTPRequestContentLength(int(resp.ReadBytes)))
}
@@ -175,12 +177,12 @@ func (o OldHTTPServer) scheme(https bool) attribute.KeyValue { // nolint:revive
type OldHTTPClient struct{}
-func (o OldHTTPClient) RequestTraceAttrs(req *http.Request) []attribute.KeyValue {
- return semconvutil.HTTPClientRequest(req)
+func (o OldHTTPClient) RequestTraceAttrs(req *http.Request, attrs []attribute.KeyValue) []attribute.KeyValue {
+ return semconvutil.HTTPClientRequest(req, attrs)
}
-func (o OldHTTPClient) ResponseTraceAttrs(resp *http.Response) []attribute.KeyValue {
- return semconvutil.HTTPClientResponse(resp)
+func (o OldHTTPClient) ResponseTraceAttrs(resp *http.Response, attrs []attribute.KeyValue) []attribute.KeyValue {
+ return semconvutil.HTTPClientResponse(resp, attrs)
}
func (o OldHTTPClient) MetricAttributes(req *http.Request, statusCode int, additionalAttributes []attribute.KeyValue) []attribute.KeyValue {
@@ -264,3 +266,8 @@ func (o OldHTTPClient) createMeasures(meter metric.Meter) (metric.Int64Counter,
return requestBytesCounter, responseBytesCounter, latencyMeasure
}
+
+// TraceAttributes returns attributes for httptrace.
+func (c OldHTTPClient) TraceAttributes(host string, attrs []attribute.KeyValue) []attribute.KeyValue {
+ return append(attrs, semconv.NetHostName(host))
+}
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/httpconv.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/httpconv.go
index a73bb06e90..b997354793 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/httpconv.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/httpconv.go
@@ -1,14 +1,16 @@
-// Code created by gotmpl. DO NOT MODIFY.
+// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/semconvutil/httpconv.go.tmpl
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
+// Package semconvutil provides OpenTelemetry semantic convention utilities.
package semconvutil // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil"
import (
"fmt"
"net/http"
+ "slices"
"strings"
"go.opentelemetry.io/otel/attribute"
@@ -16,6 +18,11 @@ import (
semconv "go.opentelemetry.io/otel/semconv/v1.20.0"
)
+type HTTPServerRequestOptions struct {
+ // If set, this is used as value for the "http.client_ip" attribute.
+ HTTPClientIP string
+}
+
// HTTPClientResponse returns trace attributes for an HTTP response received by a
// client from a server. It will return the following attributes if the related
// values are defined in resp: "http.status.code",
@@ -26,9 +33,9 @@ import (
// attributes. If a complete set of attributes can be generated using the
// request contained in resp. For example:
//
-// append(HTTPClientResponse(resp), ClientRequest(resp.Request)...)
-func HTTPClientResponse(resp *http.Response) []attribute.KeyValue {
- return hc.ClientResponse(resp)
+// HTTPClientResponse(resp, ClientRequest(resp.Request)))
+func HTTPClientResponse(resp *http.Response, attrs []attribute.KeyValue) []attribute.KeyValue {
+ return hc.ClientResponse(resp, attrs)
}
// HTTPClientRequest returns trace attributes for an HTTP request made by a client.
@@ -36,8 +43,8 @@ func HTTPClientResponse(resp *http.Response) []attribute.KeyValue {
// "net.peer.name". The following attributes are returned if the related values
// are defined in req: "net.peer.port", "user_agent.original",
// "http.request_content_length".
-func HTTPClientRequest(req *http.Request) []attribute.KeyValue {
- return hc.ClientRequest(req)
+func HTTPClientRequest(req *http.Request, attrs []attribute.KeyValue) []attribute.KeyValue {
+ return hc.ClientRequest(req, attrs)
}
// HTTPClientRequestMetrics returns metric attributes for an HTTP request made by a client.
@@ -75,8 +82,8 @@ func HTTPClientStatus(code int) (codes.Code, string) {
// "http.target", "net.host.name". The following attributes are returned if
// they related values are defined in req: "net.host.port", "net.sock.peer.addr",
// "net.sock.peer.port", "user_agent.original", "http.client_ip".
-func HTTPServerRequest(server string, req *http.Request) []attribute.KeyValue {
- return hc.ServerRequest(server, req)
+func HTTPServerRequest(server string, req *http.Request, opts HTTPServerRequestOptions, attrs []attribute.KeyValue) []attribute.KeyValue {
+ return hc.ServerRequest(server, req, opts, attrs)
}
// HTTPServerRequestMetrics returns metric attributes for an HTTP request received by a
@@ -153,8 +160,8 @@ var hc = &httpConv{
// attributes. If a complete set of attributes can be generated using the
// request contained in resp. For example:
//
-// append(ClientResponse(resp), ClientRequest(resp.Request)...)
-func (c *httpConv) ClientResponse(resp *http.Response) []attribute.KeyValue {
+// ClientResponse(resp, ClientRequest(resp.Request))
+func (c *httpConv) ClientResponse(resp *http.Response, attrs []attribute.KeyValue) []attribute.KeyValue {
/* The following semantic conventions are returned if present:
http.status_code int
http.response_content_length int
@@ -166,8 +173,11 @@ func (c *httpConv) ClientResponse(resp *http.Response) []attribute.KeyValue {
if resp.ContentLength > 0 {
n++
}
+ if n == 0 {
+ return attrs
+ }
- attrs := make([]attribute.KeyValue, 0, n)
+ attrs = slices.Grow(attrs, n)
if resp.StatusCode > 0 {
attrs = append(attrs, c.HTTPStatusCodeKey.Int(resp.StatusCode))
}
@@ -182,7 +192,7 @@ func (c *httpConv) ClientResponse(resp *http.Response) []attribute.KeyValue {
// "net.peer.name". The following attributes are returned if the related values
// are defined in req: "net.peer.port", "user_agent.original",
// "http.request_content_length", "user_agent.original".
-func (c *httpConv) ClientRequest(req *http.Request) []attribute.KeyValue {
+func (c *httpConv) ClientRequest(req *http.Request, attrs []attribute.KeyValue) []attribute.KeyValue {
/* The following semantic conventions are returned if present:
http.method string
user_agent.original string
@@ -221,8 +231,7 @@ func (c *httpConv) ClientRequest(req *http.Request) []attribute.KeyValue {
n++
}
- attrs := make([]attribute.KeyValue, 0, n)
-
+ attrs = slices.Grow(attrs, n)
attrs = append(attrs, c.method(req.Method))
var u string
@@ -305,7 +314,7 @@ func (c *httpConv) ClientRequestMetrics(req *http.Request) []attribute.KeyValue
// related values are defined in req: "net.host.port", "net.sock.peer.addr",
// "net.sock.peer.port", "user_agent.original", "http.client_ip",
// "net.protocol.name", "net.protocol.version".
-func (c *httpConv) ServerRequest(server string, req *http.Request) []attribute.KeyValue {
+func (c *httpConv) ServerRequest(server string, req *http.Request, opts HTTPServerRequestOptions, attrs []attribute.KeyValue) []attribute.KeyValue {
/* The following semantic conventions are returned if present:
http.method string
http.scheme string
@@ -358,7 +367,17 @@ func (c *httpConv) ServerRequest(server string, req *http.Request) []attribute.K
n++
}
- clientIP := serverClientIP(req.Header.Get("X-Forwarded-For"))
+ // For client IP, use, in order:
+ // 1. The value passed in the options
+ // 2. The value in the X-Forwarded-For header
+ // 3. The peer address
+ clientIP := opts.HTTPClientIP
+ if clientIP == "" {
+ clientIP = serverClientIP(req.Header.Get("X-Forwarded-For"))
+ if clientIP == "" {
+ clientIP = peer
+ }
+ }
if clientIP != "" {
n++
}
@@ -378,7 +397,7 @@ func (c *httpConv) ServerRequest(server string, req *http.Request) []attribute.K
n++
}
- attrs := make([]attribute.KeyValue, 0, n)
+ attrs = slices.Grow(attrs, n)
attrs = append(attrs, c.method(req.Method))
attrs = append(attrs, c.scheme(req.TLS != nil))
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/netconv.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/netconv.go
index b80a1db61f..df97255e41 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/netconv.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/netconv.go
@@ -1,4 +1,4 @@
-// Code created by gotmpl. DO NOT MODIFY.
+// Code generated by gotmpl. DO NOT MODIFY.
// source: internal/shared/semconvutil/netconv.go.tmpl
// Copyright The OpenTelemetry Authors
@@ -200,6 +200,15 @@ func splitHostPort(hostport string) (host string, port int) {
func netProtocol(proto string) (name string, version string) {
name, version, _ = strings.Cut(proto, "/")
- name = strings.ToLower(name)
+ switch name {
+ case "HTTP":
+ name = "http"
+ case "QUIC":
+ name = "quic"
+ case "SPDY":
+ name = "spdy"
+ default:
+ name = strings.ToLower(name)
+ }
return name, version
}
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/labeler.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/labeler.go
index ea504e396f..d62ce44b00 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/labeler.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/labeler.go
@@ -35,14 +35,14 @@ func (l *Labeler) Get() []attribute.KeyValue {
type labelerContextKeyType int
-const lablelerContextKey labelerContextKeyType = 0
+const labelerContextKey labelerContextKeyType = 0
// ContextWithLabeler returns a new context with the provided Labeler instance.
// Attributes added to the specified labeler will be injected into metrics
// emitted by the instrumentation. Only one labeller can be injected into the
// context. Injecting it multiple times will override the previous calls.
func ContextWithLabeler(parent context.Context, l *Labeler) context.Context {
- return context.WithValue(parent, lablelerContextKey, l)
+ return context.WithValue(parent, labelerContextKey, l)
}
// LabelerFromContext retrieves a Labeler instance from the provided context if
@@ -50,7 +50,7 @@ func ContextWithLabeler(parent context.Context, l *Labeler) context.Context {
// Labeler is returned and the second return value is false. In this case it is
// safe to use the Labeler but any attributes added to it will not be used.
func LabelerFromContext(ctx context.Context) (*Labeler, bool) {
- l, ok := ctx.Value(lablelerContextKey).(*Labeler)
+ l, ok := ctx.Value(labelerContextKey).(*Labeler)
if !ok {
l = &Labeler{}
}
diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go
index 386f09e1b7..6be4c1fde2 100644
--- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go
+++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go
@@ -5,13 +5,6 @@ package otelhttp // import "go.opentelemetry.io/contrib/instrumentation/net/http
// Version is the current release version of the otelhttp instrumentation.
func Version() string {
- return "0.59.0"
+ return "0.61.0"
// This string is updated by the pre_release.sh script during release
}
-
-// SemVersion is the semantic version to be supplied to tracer/meter creation.
-//
-// Deprecated: Use [Version] instead.
-func SemVersion() string {
- return Version()
-}
diff --git a/vendor/golang.org/x/crypto/ed25519/ed25519.go b/vendor/golang.org/x/crypto/ed25519/ed25519.go
index 59b3a95a7d..df453dcce0 100644
--- a/vendor/golang.org/x/crypto/ed25519/ed25519.go
+++ b/vendor/golang.org/x/crypto/ed25519/ed25519.go
@@ -2,16 +2,19 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Package ed25519 implements the Ed25519 signature algorithm. See
-// https://ed25519.cr.yp.to/.
+// Package ed25519 implements the Ed25519 signature algorithm.
//
// These functions are also compatible with the “Ed25519” function defined in
-// RFC 8032. However, unlike RFC 8032's formulation, this package's private key
+// [RFC 8032]. However, unlike RFC 8032's formulation, this package's private key
// representation includes a public key suffix to make multiple signing
// operations with the same key more efficient. This package refers to the RFC
// 8032 private key as the “seed”.
//
-// This package is a wrapper around the standard library crypto/ed25519 package.
+// The ed25519 package is a wrapper for the Ed25519 implementation in the
+// crypto/ed25519 package. It is [frozen] and is not accepting new features.
+//
+// [RFC 8032]: https://datatracker.ietf.org/doc/html/rfc8032
+// [frozen]: https://go.dev/wiki/Frozen
package ed25519
import (
diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go b/vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go
index 3685b34458..75df77406d 100644
--- a/vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go
+++ b/vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go
@@ -3,6 +3,10 @@
// license that can be found in the LICENSE file.
// Package salsa provides low-level access to functions in the Salsa family.
+//
+// Deprecated: this package exposes unsafe low-level operations. New applications
+// should consider using the AEAD construction in golang.org/x/crypto/chacha20poly1305
+// instead. Existing users should migrate to golang.org/x/crypto/salsa20.
package salsa
import "math/bits"
diff --git a/vendor/golang.org/x/net/context/context.go b/vendor/golang.org/x/net/context/context.go
index db1c95fab1..24cea68820 100644
--- a/vendor/golang.org/x/net/context/context.go
+++ b/vendor/golang.org/x/net/context/context.go
@@ -2,44 +2,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Package context defines the Context type, which carries deadlines,
-// cancellation signals, and other request-scoped values across API boundaries
-// and between processes.
-// As of Go 1.7 this package is available in the standard library under the
-// name [context], and migrating to it can be done automatically with [go fix].
-//
-// Incoming requests to a server should create a [Context], and outgoing
-// calls to servers should accept a Context. The chain of function
-// calls between them must propagate the Context, optionally replacing
-// it with a derived Context created using [WithCancel], [WithDeadline],
-// [WithTimeout], or [WithValue].
-//
-// Programs that use Contexts should follow these rules to keep interfaces
-// consistent across packages and enable static analysis tools to check context
-// propagation:
-//
-// Do not store Contexts inside a struct type; instead, pass a Context
-// explicitly to each function that needs it. This is discussed further in
-// https://go.dev/blog/context-and-structs. The Context should be the first
-// parameter, typically named ctx:
-//
-// func DoSomething(ctx context.Context, arg Arg) error {
-// // ... use ctx ...
-// }
-//
-// Do not pass a nil [Context], even if a function permits it. Pass [context.TODO]
-// if you are unsure about which Context to use.
-//
-// Use context Values only for request-scoped data that transits processes and
-// APIs, not for passing optional parameters to functions.
+// Package context has been superseded by the standard library [context] package.
//
-// The same Context may be passed to functions running in different goroutines;
-// Contexts are safe for simultaneous use by multiple goroutines.
-//
-// See https://go.dev/blog/context for example code for a server that uses
-// Contexts.
-//
-// [go fix]: https://go.dev/cmd/go#hdr-Update_packages_to_use_new_APIs
+// Deprecated: Use the standard library context package instead.
package context
import (
@@ -51,36 +16,37 @@ import (
// API boundaries.
//
// Context's methods may be called by multiple goroutines simultaneously.
+//
+//go:fix inline
type Context = context.Context
// Canceled is the error returned by [Context.Err] when the context is canceled
// for some reason other than its deadline passing.
+//
+//go:fix inline
var Canceled = context.Canceled
// DeadlineExceeded is the error returned by [Context.Err] when the context is canceled
// due to its deadline passing.
+//
+//go:fix inline
var DeadlineExceeded = context.DeadlineExceeded
// Background returns a non-nil, empty Context. It is never canceled, has no
// values, and has no deadline. It is typically used by the main function,
// initialization, and tests, and as the top-level Context for incoming
// requests.
-func Background() Context {
- return background
-}
+//
+//go:fix inline
+func Background() Context { return context.Background() }
// TODO returns a non-nil, empty Context. Code should use context.TODO when
// it's unclear which Context to use or it is not yet available (because the
// surrounding function has not yet been extended to accept a Context
// parameter).
-func TODO() Context {
- return todo
-}
-
-var (
- background = context.Background()
- todo = context.TODO()
-)
+//
+//go:fix inline
+func TODO() Context { return context.TODO() }
// A CancelFunc tells an operation to abandon its work.
// A CancelFunc does not wait for the work to stop.
@@ -95,6 +61,8 @@ type CancelFunc = context.CancelFunc
//
// Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this [Context] complete.
+//
+//go:fix inline
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
return context.WithCancel(parent)
}
@@ -108,6 +76,8 @@ func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
//
// Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this [Context] complete.
+//
+//go:fix inline
func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {
return context.WithDeadline(parent, d)
}
@@ -122,6 +92,8 @@ func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {
// defer cancel() // releases resources if slowOperation completes before timeout elapses
// return slowOperation(ctx)
// }
+//
+//go:fix inline
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
return context.WithTimeout(parent, timeout)
}
@@ -139,6 +111,8 @@ func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
// interface{}, context keys often have concrete type
// struct{}. Alternatively, exported context key variables' static
// type should be a pointer or interface.
+//
+//go:fix inline
func WithValue(parent Context, key, val interface{}) Context {
return context.WithValue(parent, key, val)
}
diff --git a/vendor/golang.org/x/net/html/escape.go b/vendor/golang.org/x/net/html/escape.go
index 04c6bec210..12f2273706 100644
--- a/vendor/golang.org/x/net/html/escape.go
+++ b/vendor/golang.org/x/net/html/escape.go
@@ -299,7 +299,7 @@ func escape(w writer, s string) error {
case '\r':
esc = "
"
default:
- panic("unrecognized escape character")
+ panic("html: unrecognized escape character")
}
s = s[i+1:]
if _, err := w.WriteString(esc); err != nil {
diff --git a/vendor/golang.org/x/net/html/parse.go b/vendor/golang.org/x/net/html/parse.go
index 518ee4c94e..88fc0056a3 100644
--- a/vendor/golang.org/x/net/html/parse.go
+++ b/vendor/golang.org/x/net/html/parse.go
@@ -136,7 +136,7 @@ func (p *parser) indexOfElementInScope(s scope, matchTags ...a.Atom) int {
return -1
}
default:
- panic("unreachable")
+ panic(fmt.Sprintf("html: internal error: indexOfElementInScope unknown scope: %d", s))
}
}
switch s {
@@ -179,7 +179,7 @@ func (p *parser) clearStackToContext(s scope) {
return
}
default:
- panic("unreachable")
+ panic(fmt.Sprintf("html: internal error: clearStackToContext unknown scope: %d", s))
}
}
}
@@ -231,7 +231,14 @@ func (p *parser) addChild(n *Node) {
}
if n.Type == ElementNode {
- p.oe = append(p.oe, n)
+ p.insertOpenElement(n)
+ }
+}
+
+func (p *parser) insertOpenElement(n *Node) {
+ p.oe = append(p.oe, n)
+ if len(p.oe) > 512 {
+ panic("html: open stack of elements exceeds 512 nodes")
}
}
@@ -810,7 +817,7 @@ func afterHeadIM(p *parser) bool {
p.im = inFramesetIM
return true
case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title:
- p.oe = append(p.oe, p.head)
+ p.insertOpenElement(p.head)
defer p.oe.remove(p.head)
return inHeadIM(p)
case a.Head:
@@ -1678,7 +1685,7 @@ func inTableBodyIM(p *parser) bool {
return inTableIM(p)
}
-// Section 12.2.6.4.14.
+// Section 13.2.6.4.14.
func inRowIM(p *parser) bool {
switch p.tok.Type {
case StartTagToken:
@@ -1690,7 +1697,9 @@ func inRowIM(p *parser) bool {
p.im = inCellIM
return true
case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Tfoot, a.Thead, a.Tr:
- if p.popUntil(tableScope, a.Tr) {
+ if p.elementInScope(tableScope, a.Tr) {
+ p.clearStackToContext(tableRowScope)
+ p.oe.pop()
p.im = inTableBodyIM
return false
}
@@ -1700,22 +1709,28 @@ func inRowIM(p *parser) bool {
case EndTagToken:
switch p.tok.DataAtom {
case a.Tr:
- if p.popUntil(tableScope, a.Tr) {
+ if p.elementInScope(tableScope, a.Tr) {
+ p.clearStackToContext(tableRowScope)
+ p.oe.pop()
p.im = inTableBodyIM
return true
}
// Ignore the token.
return true
case a.Table:
- if p.popUntil(tableScope, a.Tr) {
+ if p.elementInScope(tableScope, a.Tr) {
+ p.clearStackToContext(tableRowScope)
+ p.oe.pop()
p.im = inTableBodyIM
return false
}
// Ignore the token.
return true
case a.Tbody, a.Tfoot, a.Thead:
- if p.elementInScope(tableScope, p.tok.DataAtom) {
- p.parseImpliedToken(EndTagToken, a.Tr, a.Tr.String())
+ if p.elementInScope(tableScope, p.tok.DataAtom) && p.elementInScope(tableScope, a.Tr) {
+ p.clearStackToContext(tableRowScope)
+ p.oe.pop()
+ p.im = inTableBodyIM
return false
}
// Ignore the token.
@@ -2222,16 +2237,20 @@ func parseForeignContent(p *parser) bool {
p.acknowledgeSelfClosingTag()
}
case EndTagToken:
+ if strings.EqualFold(p.oe[len(p.oe)-1].Data, p.tok.Data) {
+ p.oe = p.oe[:len(p.oe)-1]
+ return true
+ }
for i := len(p.oe) - 1; i >= 0; i-- {
- if p.oe[i].Namespace == "" {
- return p.im(p)
- }
if strings.EqualFold(p.oe[i].Data, p.tok.Data) {
p.oe = p.oe[:i]
+ return true
+ }
+ if i > 0 && p.oe[i-1].Namespace == "" {
break
}
}
- return true
+ return p.im(p)
default:
// Ignore the token.
}
@@ -2312,9 +2331,13 @@ func (p *parser) parseCurrentToken() {
}
}
-func (p *parser) parse() error {
+func (p *parser) parse() (err error) {
+ defer func() {
+ if panicErr := recover(); panicErr != nil {
+ err = fmt.Errorf("%s", panicErr)
+ }
+ }()
// Iterate until EOF. Any other error will cause an early return.
- var err error
for err != io.EOF {
// CDATA sections are allowed only in foreign content.
n := p.oe.top()
@@ -2343,6 +2366,8 @@ func (p *parser) parse() error {
// s. Conversely, explicit s in r's data can be silently dropped,
// with no corresponding node in the resulting tree.
//
+// Parse will reject HTML that is nested deeper than 512 elements.
+//
// The input is assumed to be UTF-8 encoded.
func Parse(r io.Reader) (*Node, error) {
return ParseWithOptions(r)
diff --git a/vendor/golang.org/x/net/html/render.go b/vendor/golang.org/x/net/html/render.go
index e8c1233455..0157d89e1f 100644
--- a/vendor/golang.org/x/net/html/render.go
+++ b/vendor/golang.org/x/net/html/render.go
@@ -184,7 +184,7 @@ func render1(w writer, n *Node) error {
return err
}
- // Add initial newline where there is danger of a newline beging ignored.
+ // Add initial newline where there is danger of a newline being ignored.
if c := n.FirstChild; c != nil && c.Type == TextNode && strings.HasPrefix(c.Data, "\n") {
switch n.Data {
case "pre", "listing", "textarea":
diff --git a/vendor/golang.org/x/net/http2/config.go b/vendor/golang.org/x/net/http2/config.go
index ca645d9a1a..8a7a89d016 100644
--- a/vendor/golang.org/x/net/http2/config.go
+++ b/vendor/golang.org/x/net/http2/config.go
@@ -27,6 +27,7 @@ import (
// - If the resulting value is zero or out of range, use a default.
type http2Config struct {
MaxConcurrentStreams uint32
+ StrictMaxConcurrentRequests bool
MaxDecoderHeaderTableSize uint32
MaxEncoderHeaderTableSize uint32
MaxReadFrameSize uint32
@@ -55,7 +56,7 @@ func configFromServer(h1 *http.Server, h2 *Server) http2Config {
PermitProhibitedCipherSuites: h2.PermitProhibitedCipherSuites,
CountError: h2.CountError,
}
- fillNetHTTPServerConfig(&conf, h1)
+ fillNetHTTPConfig(&conf, h1.HTTP2)
setConfigDefaults(&conf, true)
return conf
}
@@ -64,12 +65,13 @@ func configFromServer(h1 *http.Server, h2 *Server) http2Config {
// (the net/http Transport).
func configFromTransport(h2 *Transport) http2Config {
conf := http2Config{
- MaxEncoderHeaderTableSize: h2.MaxEncoderHeaderTableSize,
- MaxDecoderHeaderTableSize: h2.MaxDecoderHeaderTableSize,
- MaxReadFrameSize: h2.MaxReadFrameSize,
- SendPingTimeout: h2.ReadIdleTimeout,
- PingTimeout: h2.PingTimeout,
- WriteByteTimeout: h2.WriteByteTimeout,
+ StrictMaxConcurrentRequests: h2.StrictMaxConcurrentStreams,
+ MaxEncoderHeaderTableSize: h2.MaxEncoderHeaderTableSize,
+ MaxDecoderHeaderTableSize: h2.MaxDecoderHeaderTableSize,
+ MaxReadFrameSize: h2.MaxReadFrameSize,
+ SendPingTimeout: h2.ReadIdleTimeout,
+ PingTimeout: h2.PingTimeout,
+ WriteByteTimeout: h2.WriteByteTimeout,
}
// Unlike most config fields, where out-of-range values revert to the default,
@@ -81,7 +83,7 @@ func configFromTransport(h2 *Transport) http2Config {
}
if h2.t1 != nil {
- fillNetHTTPTransportConfig(&conf, h2.t1)
+ fillNetHTTPConfig(&conf, h2.t1.HTTP2)
}
setConfigDefaults(&conf, false)
return conf
@@ -120,3 +122,48 @@ func adjustHTTP1MaxHeaderSize(n int64) int64 {
const typicalHeaders = 10 // conservative
return n + typicalHeaders*perFieldOverhead
}
+
+func fillNetHTTPConfig(conf *http2Config, h2 *http.HTTP2Config) {
+ if h2 == nil {
+ return
+ }
+ if h2.MaxConcurrentStreams != 0 {
+ conf.MaxConcurrentStreams = uint32(h2.MaxConcurrentStreams)
+ }
+ if http2ConfigStrictMaxConcurrentRequests(h2) {
+ conf.StrictMaxConcurrentRequests = true
+ }
+ if h2.MaxEncoderHeaderTableSize != 0 {
+ conf.MaxEncoderHeaderTableSize = uint32(h2.MaxEncoderHeaderTableSize)
+ }
+ if h2.MaxDecoderHeaderTableSize != 0 {
+ conf.MaxDecoderHeaderTableSize = uint32(h2.MaxDecoderHeaderTableSize)
+ }
+ if h2.MaxConcurrentStreams != 0 {
+ conf.MaxConcurrentStreams = uint32(h2.MaxConcurrentStreams)
+ }
+ if h2.MaxReadFrameSize != 0 {
+ conf.MaxReadFrameSize = uint32(h2.MaxReadFrameSize)
+ }
+ if h2.MaxReceiveBufferPerConnection != 0 {
+ conf.MaxUploadBufferPerConnection = int32(h2.MaxReceiveBufferPerConnection)
+ }
+ if h2.MaxReceiveBufferPerStream != 0 {
+ conf.MaxUploadBufferPerStream = int32(h2.MaxReceiveBufferPerStream)
+ }
+ if h2.SendPingTimeout != 0 {
+ conf.SendPingTimeout = h2.SendPingTimeout
+ }
+ if h2.PingTimeout != 0 {
+ conf.PingTimeout = h2.PingTimeout
+ }
+ if h2.WriteByteTimeout != 0 {
+ conf.WriteByteTimeout = h2.WriteByteTimeout
+ }
+ if h2.PermitProhibitedCipherSuites {
+ conf.PermitProhibitedCipherSuites = true
+ }
+ if h2.CountError != nil {
+ conf.CountError = h2.CountError
+ }
+}
diff --git a/vendor/golang.org/x/net/http2/config_go124.go b/vendor/golang.org/x/net/http2/config_go124.go
deleted file mode 100644
index 5b516c55ff..0000000000
--- a/vendor/golang.org/x/net/http2/config_go124.go
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2024 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.24
-
-package http2
-
-import "net/http"
-
-// fillNetHTTPServerConfig sets fields in conf from srv.HTTP2.
-func fillNetHTTPServerConfig(conf *http2Config, srv *http.Server) {
- fillNetHTTPConfig(conf, srv.HTTP2)
-}
-
-// fillNetHTTPTransportConfig sets fields in conf from tr.HTTP2.
-func fillNetHTTPTransportConfig(conf *http2Config, tr *http.Transport) {
- fillNetHTTPConfig(conf, tr.HTTP2)
-}
-
-func fillNetHTTPConfig(conf *http2Config, h2 *http.HTTP2Config) {
- if h2 == nil {
- return
- }
- if h2.MaxConcurrentStreams != 0 {
- conf.MaxConcurrentStreams = uint32(h2.MaxConcurrentStreams)
- }
- if h2.MaxEncoderHeaderTableSize != 0 {
- conf.MaxEncoderHeaderTableSize = uint32(h2.MaxEncoderHeaderTableSize)
- }
- if h2.MaxDecoderHeaderTableSize != 0 {
- conf.MaxDecoderHeaderTableSize = uint32(h2.MaxDecoderHeaderTableSize)
- }
- if h2.MaxConcurrentStreams != 0 {
- conf.MaxConcurrentStreams = uint32(h2.MaxConcurrentStreams)
- }
- if h2.MaxReadFrameSize != 0 {
- conf.MaxReadFrameSize = uint32(h2.MaxReadFrameSize)
- }
- if h2.MaxReceiveBufferPerConnection != 0 {
- conf.MaxUploadBufferPerConnection = int32(h2.MaxReceiveBufferPerConnection)
- }
- if h2.MaxReceiveBufferPerStream != 0 {
- conf.MaxUploadBufferPerStream = int32(h2.MaxReceiveBufferPerStream)
- }
- if h2.SendPingTimeout != 0 {
- conf.SendPingTimeout = h2.SendPingTimeout
- }
- if h2.PingTimeout != 0 {
- conf.PingTimeout = h2.PingTimeout
- }
- if h2.WriteByteTimeout != 0 {
- conf.WriteByteTimeout = h2.WriteByteTimeout
- }
- if h2.PermitProhibitedCipherSuites {
- conf.PermitProhibitedCipherSuites = true
- }
- if h2.CountError != nil {
- conf.CountError = h2.CountError
- }
-}
diff --git a/vendor/golang.org/x/net/http2/config_go125.go b/vendor/golang.org/x/net/http2/config_go125.go
new file mode 100644
index 0000000000..b4373fe33c
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/config_go125.go
@@ -0,0 +1,15 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !go1.26
+
+package http2
+
+import (
+ "net/http"
+)
+
+func http2ConfigStrictMaxConcurrentRequests(h2 *http.HTTP2Config) bool {
+ return false
+}
diff --git a/vendor/golang.org/x/net/http2/config_go126.go b/vendor/golang.org/x/net/http2/config_go126.go
new file mode 100644
index 0000000000..6b071c149d
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/config_go126.go
@@ -0,0 +1,15 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build go1.26
+
+package http2
+
+import (
+ "net/http"
+)
+
+func http2ConfigStrictMaxConcurrentRequests(h2 *http.HTTP2Config) bool {
+ return h2.StrictMaxConcurrentRequests
+}
diff --git a/vendor/golang.org/x/net/http2/config_pre_go124.go b/vendor/golang.org/x/net/http2/config_pre_go124.go
deleted file mode 100644
index 060fd6c64c..0000000000
--- a/vendor/golang.org/x/net/http2/config_pre_go124.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2024 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.24
-
-package http2
-
-import "net/http"
-
-// Pre-Go 1.24 fallback.
-// The Server.HTTP2 and Transport.HTTP2 config fields were added in Go 1.24.
-
-func fillNetHTTPServerConfig(conf *http2Config, srv *http.Server) {}
-
-func fillNetHTTPTransportConfig(conf *http2Config, tr *http.Transport) {}
diff --git a/vendor/golang.org/x/net/http2/frame.go b/vendor/golang.org/x/net/http2/frame.go
index db3264da8c..9a4bd123c9 100644
--- a/vendor/golang.org/x/net/http2/frame.go
+++ b/vendor/golang.org/x/net/http2/frame.go
@@ -280,6 +280,8 @@ type Framer struct {
// lastHeaderStream is non-zero if the last frame was an
// unfinished HEADERS/CONTINUATION.
lastHeaderStream uint32
+ // lastFrameType holds the type of the last frame for verifying frame order.
+ lastFrameType FrameType
maxReadSize uint32
headerBuf [frameHeaderLen]byte
@@ -347,7 +349,7 @@ func (fr *Framer) maxHeaderListSize() uint32 {
func (f *Framer) startWrite(ftype FrameType, flags Flags, streamID uint32) {
// Write the FrameHeader.
f.wbuf = append(f.wbuf[:0],
- 0, // 3 bytes of length, filled in in endWrite
+ 0, // 3 bytes of length, filled in endWrite
0,
0,
byte(ftype),
@@ -488,30 +490,41 @@ func terminalReadFrameError(err error) bool {
return err != nil
}
-// ReadFrame reads a single frame. The returned Frame is only valid
-// until the next call to ReadFrame.
+// ReadFrameHeader reads the header of the next frame.
+// It reads the 9-byte fixed frame header, and does not read any portion of the
+// frame payload. The caller is responsible for consuming the payload, either
+// with ReadFrameForHeader or directly from the Framer's io.Reader.
//
-// If the frame is larger than previously set with SetMaxReadFrameSize, the
-// returned error is ErrFrameTooLarge. Other errors may be of type
-// ConnectionError, StreamError, or anything else from the underlying
-// reader.
+// If the frame is larger than previously set with SetMaxReadFrameSize, it
+// returns the frame header and ErrFrameTooLarge.
//
-// If ReadFrame returns an error and a non-nil Frame, the Frame's StreamID
-// indicates the stream responsible for the error.
-func (fr *Framer) ReadFrame() (Frame, error) {
+// If the returned FrameHeader.StreamID is non-zero, it indicates the stream
+// responsible for the error.
+func (fr *Framer) ReadFrameHeader() (FrameHeader, error) {
fr.errDetail = nil
- if fr.lastFrame != nil {
- fr.lastFrame.invalidate()
- }
fh, err := readFrameHeader(fr.headerBuf[:], fr.r)
if err != nil {
- return nil, err
+ return fh, err
}
if fh.Length > fr.maxReadSize {
if fh == invalidHTTP1LookingFrameHeader() {
- return nil, fmt.Errorf("http2: failed reading the frame payload: %w, note that the frame header looked like an HTTP/1.1 header", ErrFrameTooLarge)
+ return fh, fmt.Errorf("http2: failed reading the frame payload: %w, note that the frame header looked like an HTTP/1.1 header", ErrFrameTooLarge)
}
- return nil, ErrFrameTooLarge
+ return fh, ErrFrameTooLarge
+ }
+ if err := fr.checkFrameOrder(fh); err != nil {
+ return fh, err
+ }
+ return fh, nil
+}
+
+// ReadFrameForHeader reads the payload for the frame with the given FrameHeader.
+//
+// It behaves identically to ReadFrame, other than not checking the maximum
+// frame size.
+func (fr *Framer) ReadFrameForHeader(fh FrameHeader) (Frame, error) {
+ if fr.lastFrame != nil {
+ fr.lastFrame.invalidate()
}
payload := fr.getReadBuf(fh.Length)
if _, err := io.ReadFull(fr.r, payload); err != nil {
@@ -527,9 +540,7 @@ func (fr *Framer) ReadFrame() (Frame, error) {
}
return nil, err
}
- if err := fr.checkFrameOrder(f); err != nil {
- return nil, err
- }
+ fr.lastFrame = f
if fr.logReads {
fr.debugReadLoggerf("http2: Framer %p: read %v", fr, summarizeFrame(f))
}
@@ -539,6 +550,24 @@ func (fr *Framer) ReadFrame() (Frame, error) {
return f, nil
}
+// ReadFrame reads a single frame. The returned Frame is only valid
+// until the next call to ReadFrame or ReadFrameBodyForHeader.
+//
+// If the frame is larger than previously set with SetMaxReadFrameSize, the
+// returned error is ErrFrameTooLarge. Other errors may be of type
+// ConnectionError, StreamError, or anything else from the underlying
+// reader.
+//
+// If ReadFrame returns an error and a non-nil Frame, the Frame's StreamID
+// indicates the stream responsible for the error.
+func (fr *Framer) ReadFrame() (Frame, error) {
+ fh, err := fr.ReadFrameHeader()
+ if err != nil {
+ return nil, err
+ }
+ return fr.ReadFrameForHeader(fh)
+}
+
// connError returns ConnectionError(code) but first
// stashes away a public reason to the caller can optionally relay it
// to the peer before hanging up on them. This might help others debug
@@ -551,20 +580,19 @@ func (fr *Framer) connError(code ErrCode, reason string) error {
// checkFrameOrder reports an error if f is an invalid frame to return
// next from ReadFrame. Mostly it checks whether HEADERS and
// CONTINUATION frames are contiguous.
-func (fr *Framer) checkFrameOrder(f Frame) error {
- last := fr.lastFrame
- fr.lastFrame = f
+func (fr *Framer) checkFrameOrder(fh FrameHeader) error {
+ lastType := fr.lastFrameType
+ fr.lastFrameType = fh.Type
if fr.AllowIllegalReads {
return nil
}
- fh := f.Header()
if fr.lastHeaderStream != 0 {
if fh.Type != FrameContinuation {
return fr.connError(ErrCodeProtocol,
fmt.Sprintf("got %s for stream %d; expected CONTINUATION following %s for stream %d",
fh.Type, fh.StreamID,
- last.Header().Type, fr.lastHeaderStream))
+ lastType, fr.lastHeaderStream))
}
if fh.StreamID != fr.lastHeaderStream {
return fr.connError(ErrCodeProtocol,
@@ -1152,7 +1180,16 @@ type PriorityFrame struct {
PriorityParam
}
-// PriorityParam are the stream prioritzation parameters.
+var defaultRFC9218Priority = PriorityParam{
+ incremental: 0,
+ urgency: 3,
+}
+
+// Note that HTTP/2 has had two different prioritization schemes, and
+// PriorityParam struct below is a superset of both schemes. The exported
+// symbols are from RFC 7540 and the non-exported ones are from RFC 9218.
+
+// PriorityParam are the stream prioritization parameters.
type PriorityParam struct {
// StreamDep is a 31-bit stream identifier for the
// stream that this stream depends on. Zero means no
@@ -1167,6 +1204,20 @@ type PriorityParam struct {
// the spec, "Add one to the value to obtain a weight between
// 1 and 256."
Weight uint8
+
+ // "The urgency (u) parameter value is Integer (see Section 3.3.1 of
+ // [STRUCTURED-FIELDS]), between 0 and 7 inclusive, in descending order of
+ // priority. The default is 3."
+ urgency uint8
+
+ // "The incremental (i) parameter value is Boolean (see Section 3.3.6 of
+ // [STRUCTURED-FIELDS]). It indicates if an HTTP response can be processed
+ // incrementally, i.e., provide some meaningful output as chunks of the
+ // response arrive."
+ //
+ // We use uint8 (i.e. 0 is false, 1 is true) instead of bool so we can
+ // avoid unnecessary type conversions and because either type takes 1 byte.
+ incremental uint8
}
func (p PriorityParam) IsZero() bool {
diff --git a/vendor/golang.org/x/net/http2/gotrack.go b/vendor/golang.org/x/net/http2/gotrack.go
index 9933c9f8c7..9921ca096d 100644
--- a/vendor/golang.org/x/net/http2/gotrack.go
+++ b/vendor/golang.org/x/net/http2/gotrack.go
@@ -15,21 +15,32 @@ import (
"runtime"
"strconv"
"sync"
+ "sync/atomic"
)
var DebugGoroutines = os.Getenv("DEBUG_HTTP2_GOROUTINES") == "1"
+// Setting DebugGoroutines to false during a test to disable goroutine debugging
+// results in race detector complaints when a test leaves goroutines running before
+// returning. Tests shouldn't do this, of course, but when they do it generally shows
+// up as infrequent, hard-to-debug flakes. (See #66519.)
+//
+// Disable goroutine debugging during individual tests with an atomic bool.
+// (Note that it's safe to enable/disable debugging mid-test, so the actual race condition
+// here is harmless.)
+var disableDebugGoroutines atomic.Bool
+
type goroutineLock uint64
func newGoroutineLock() goroutineLock {
- if !DebugGoroutines {
+ if !DebugGoroutines || disableDebugGoroutines.Load() {
return 0
}
return goroutineLock(curGoroutineID())
}
func (g goroutineLock) check() {
- if !DebugGoroutines {
+ if !DebugGoroutines || disableDebugGoroutines.Load() {
return
}
if curGoroutineID() != uint64(g) {
@@ -38,7 +49,7 @@ func (g goroutineLock) check() {
}
func (g goroutineLock) checkNotOn() {
- if !DebugGoroutines {
+ if !DebugGoroutines || disableDebugGoroutines.Load() {
return
}
if curGoroutineID() == uint64(g) {
diff --git a/vendor/golang.org/x/net/http2/http2.go b/vendor/golang.org/x/net/http2/http2.go
index ea5ae629fd..105fe12fef 100644
--- a/vendor/golang.org/x/net/http2/http2.go
+++ b/vendor/golang.org/x/net/http2/http2.go
@@ -15,7 +15,6 @@ package http2 // import "golang.org/x/net/http2"
import (
"bufio"
- "context"
"crypto/tls"
"errors"
"fmt"
@@ -35,7 +34,6 @@ var (
VerboseLogs bool
logFrameWrites bool
logFrameReads bool
- inTests bool
// Enabling extended CONNECT by causes browsers to attempt to use
// WebSockets-over-HTTP/2. This results in problems when the server's websocket
@@ -255,15 +253,13 @@ func (cw closeWaiter) Wait() {
// idle memory usage with many connections.
type bufferedWriter struct {
_ incomparable
- group synctestGroupInterface // immutable
- conn net.Conn // immutable
- bw *bufio.Writer // non-nil when data is buffered
- byteTimeout time.Duration // immutable, WriteByteTimeout
+ conn net.Conn // immutable
+ bw *bufio.Writer // non-nil when data is buffered
+ byteTimeout time.Duration // immutable, WriteByteTimeout
}
-func newBufferedWriter(group synctestGroupInterface, conn net.Conn, timeout time.Duration) *bufferedWriter {
+func newBufferedWriter(conn net.Conn, timeout time.Duration) *bufferedWriter {
return &bufferedWriter{
- group: group,
conn: conn,
byteTimeout: timeout,
}
@@ -314,24 +310,18 @@ func (w *bufferedWriter) Flush() error {
type bufferedWriterTimeoutWriter bufferedWriter
func (w *bufferedWriterTimeoutWriter) Write(p []byte) (n int, err error) {
- return writeWithByteTimeout(w.group, w.conn, w.byteTimeout, p)
+ return writeWithByteTimeout(w.conn, w.byteTimeout, p)
}
// writeWithByteTimeout writes to conn.
// If more than timeout passes without any bytes being written to the connection,
// the write fails.
-func writeWithByteTimeout(group synctestGroupInterface, conn net.Conn, timeout time.Duration, p []byte) (n int, err error) {
+func writeWithByteTimeout(conn net.Conn, timeout time.Duration, p []byte) (n int, err error) {
if timeout <= 0 {
return conn.Write(p)
}
for {
- var now time.Time
- if group == nil {
- now = time.Now()
- } else {
- now = group.Now()
- }
- conn.SetWriteDeadline(now.Add(timeout))
+ conn.SetWriteDeadline(time.Now().Add(timeout))
nn, err := conn.Write(p[n:])
n += nn
if n == len(p) || nn == 0 || !errors.Is(err, os.ErrDeadlineExceeded) {
@@ -417,14 +407,3 @@ func (s *sorter) SortStrings(ss []string) {
// makes that struct also non-comparable, and generally doesn't add
// any size (as long as it's first).
type incomparable [0]func()
-
-// synctestGroupInterface is the methods of synctestGroup used by Server and Transport.
-// It's defined as an interface here to let us keep synctestGroup entirely test-only
-// and not a part of non-test builds.
-type synctestGroupInterface interface {
- Join()
- Now() time.Time
- NewTimer(d time.Duration) timer
- AfterFunc(d time.Duration, f func()) timer
- ContextWithTimeout(ctx context.Context, d time.Duration) (context.Context, context.CancelFunc)
-}
diff --git a/vendor/golang.org/x/net/http2/server.go b/vendor/golang.org/x/net/http2/server.go
index 51fca38f61..bdc5520ebd 100644
--- a/vendor/golang.org/x/net/http2/server.go
+++ b/vendor/golang.org/x/net/http2/server.go
@@ -176,44 +176,15 @@ type Server struct {
// so that we don't embed a Mutex in this struct, which will make the
// struct non-copyable, which might break some callers.
state *serverInternalState
-
- // Synchronization group used for testing.
- // Outside of tests, this is nil.
- group synctestGroupInterface
-}
-
-func (s *Server) markNewGoroutine() {
- if s.group != nil {
- s.group.Join()
- }
-}
-
-func (s *Server) now() time.Time {
- if s.group != nil {
- return s.group.Now()
- }
- return time.Now()
-}
-
-// newTimer creates a new time.Timer, or a synthetic timer in tests.
-func (s *Server) newTimer(d time.Duration) timer {
- if s.group != nil {
- return s.group.NewTimer(d)
- }
- return timeTimer{time.NewTimer(d)}
-}
-
-// afterFunc creates a new time.AfterFunc timer, or a synthetic timer in tests.
-func (s *Server) afterFunc(d time.Duration, f func()) timer {
- if s.group != nil {
- return s.group.AfterFunc(d, f)
- }
- return timeTimer{time.AfterFunc(d, f)}
}
type serverInternalState struct {
mu sync.Mutex
activeConns map[*serverConn]struct{}
+
+ // Pool of error channels. This is per-Server rather than global
+ // because channels can't be reused across synctest bubbles.
+ errChanPool sync.Pool
}
func (s *serverInternalState) registerConn(sc *serverConn) {
@@ -245,6 +216,27 @@ func (s *serverInternalState) startGracefulShutdown() {
s.mu.Unlock()
}
+// Global error channel pool used for uninitialized Servers.
+// We use a per-Server pool when possible to avoid using channels across synctest bubbles.
+var errChanPool = sync.Pool{
+ New: func() any { return make(chan error, 1) },
+}
+
+func (s *serverInternalState) getErrChan() chan error {
+ if s == nil {
+ return errChanPool.Get().(chan error) // Server used without calling ConfigureServer
+ }
+ return s.errChanPool.Get().(chan error)
+}
+
+func (s *serverInternalState) putErrChan(ch chan error) {
+ if s == nil {
+ errChanPool.Put(ch) // Server used without calling ConfigureServer
+ return
+ }
+ s.errChanPool.Put(ch)
+}
+
// ConfigureServer adds HTTP/2 support to a net/http Server.
//
// The configuration conf may be nil.
@@ -257,7 +249,10 @@ func ConfigureServer(s *http.Server, conf *Server) error {
if conf == nil {
conf = new(Server)
}
- conf.state = &serverInternalState{activeConns: make(map[*serverConn]struct{})}
+ conf.state = &serverInternalState{
+ activeConns: make(map[*serverConn]struct{}),
+ errChanPool: sync.Pool{New: func() any { return make(chan error, 1) }},
+ }
if h1, h2 := s, conf; h2.IdleTimeout == 0 {
if h1.IdleTimeout != 0 {
h2.IdleTimeout = h1.IdleTimeout
@@ -423,6 +418,9 @@ func (o *ServeConnOpts) handler() http.Handler {
//
// The opts parameter is optional. If nil, default values are used.
func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
+ if opts == nil {
+ opts = &ServeConnOpts{}
+ }
s.serveConn(c, opts, nil)
}
@@ -438,7 +436,7 @@ func (s *Server) serveConn(c net.Conn, opts *ServeConnOpts, newf func(*serverCon
conn: c,
baseCtx: baseCtx,
remoteAddrStr: c.RemoteAddr().String(),
- bw: newBufferedWriter(s.group, c, conf.WriteByteTimeout),
+ bw: newBufferedWriter(c, conf.WriteByteTimeout),
handler: opts.handler(),
streams: make(map[uint32]*stream),
readFrameCh: make(chan readFrameResult),
@@ -638,11 +636,11 @@ type serverConn struct {
pingSent bool
sentPingData [8]byte
goAwayCode ErrCode
- shutdownTimer timer // nil until used
- idleTimer timer // nil if unused
+ shutdownTimer *time.Timer // nil until used
+ idleTimer *time.Timer // nil if unused
readIdleTimeout time.Duration
pingTimeout time.Duration
- readIdleTimer timer // nil if unused
+ readIdleTimer *time.Timer // nil if unused
// Owned by the writeFrameAsync goroutine:
headerWriteBuf bytes.Buffer
@@ -687,12 +685,12 @@ type stream struct {
flow outflow // limits writing from Handler to client
inflow inflow // what the client is allowed to POST/etc to us
state streamState
- resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
- gotTrailerHeader bool // HEADER frame for trailers was seen
- wroteHeaders bool // whether we wrote headers (not status 100)
- readDeadline timer // nil if unused
- writeDeadline timer // nil if unused
- closeErr error // set before cw is closed
+ resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
+ gotTrailerHeader bool // HEADER frame for trailers was seen
+ wroteHeaders bool // whether we wrote headers (not status 100)
+ readDeadline *time.Timer // nil if unused
+ writeDeadline *time.Timer // nil if unused
+ closeErr error // set before cw is closed
trailer http.Header // accumulated trailers
reqTrailer http.Header // handler's Request.Trailer
@@ -848,7 +846,6 @@ type readFrameResult struct {
// consumer is done with the frame.
// It's run on its own goroutine.
func (sc *serverConn) readFrames() {
- sc.srv.markNewGoroutine()
gate := make(chan struct{})
gateDone := func() { gate <- struct{}{} }
for {
@@ -881,7 +878,6 @@ type frameWriteResult struct {
// At most one goroutine can be running writeFrameAsync at a time per
// serverConn.
func (sc *serverConn) writeFrameAsync(wr FrameWriteRequest, wd *writeData) {
- sc.srv.markNewGoroutine()
var err error
if wd == nil {
err = wr.write.writeFrame(sc)
@@ -965,22 +961,22 @@ func (sc *serverConn) serve(conf http2Config) {
sc.setConnState(http.StateIdle)
if sc.srv.IdleTimeout > 0 {
- sc.idleTimer = sc.srv.afterFunc(sc.srv.IdleTimeout, sc.onIdleTimer)
+ sc.idleTimer = time.AfterFunc(sc.srv.IdleTimeout, sc.onIdleTimer)
defer sc.idleTimer.Stop()
}
if conf.SendPingTimeout > 0 {
sc.readIdleTimeout = conf.SendPingTimeout
- sc.readIdleTimer = sc.srv.afterFunc(conf.SendPingTimeout, sc.onReadIdleTimer)
+ sc.readIdleTimer = time.AfterFunc(conf.SendPingTimeout, sc.onReadIdleTimer)
defer sc.readIdleTimer.Stop()
}
go sc.readFrames() // closed by defer sc.conn.Close above
- settingsTimer := sc.srv.afterFunc(firstSettingsTimeout, sc.onSettingsTimer)
+ settingsTimer := time.AfterFunc(firstSettingsTimeout, sc.onSettingsTimer)
defer settingsTimer.Stop()
- lastFrameTime := sc.srv.now()
+ lastFrameTime := time.Now()
loopNum := 0
for {
loopNum++
@@ -994,7 +990,7 @@ func (sc *serverConn) serve(conf http2Config) {
case res := <-sc.wroteFrameCh:
sc.wroteFrame(res)
case res := <-sc.readFrameCh:
- lastFrameTime = sc.srv.now()
+ lastFrameTime = time.Now()
// Process any written frames before reading new frames from the client since a
// written frame could have triggered a new stream to be started.
if sc.writingFrameAsync {
@@ -1077,7 +1073,7 @@ func (sc *serverConn) handlePingTimer(lastFrameReadTime time.Time) {
}
pingAt := lastFrameReadTime.Add(sc.readIdleTimeout)
- now := sc.srv.now()
+ now := time.Now()
if pingAt.After(now) {
// We received frames since arming the ping timer.
// Reset it for the next possible timeout.
@@ -1141,10 +1137,10 @@ func (sc *serverConn) readPreface() error {
errc <- nil
}
}()
- timer := sc.srv.newTimer(prefaceTimeout) // TODO: configurable on *Server?
+ timer := time.NewTimer(prefaceTimeout) // TODO: configurable on *Server?
defer timer.Stop()
select {
- case <-timer.C():
+ case <-timer.C:
return errPrefaceTimeout
case err := <-errc:
if err == nil {
@@ -1156,10 +1152,6 @@ func (sc *serverConn) readPreface() error {
}
}
-var errChanPool = sync.Pool{
- New: func() interface{} { return make(chan error, 1) },
-}
-
var writeDataPool = sync.Pool{
New: func() interface{} { return new(writeData) },
}
@@ -1167,7 +1159,7 @@ var writeDataPool = sync.Pool{
// writeDataFromHandler writes DATA response frames from a handler on
// the given stream.
func (sc *serverConn) writeDataFromHandler(stream *stream, data []byte, endStream bool) error {
- ch := errChanPool.Get().(chan error)
+ ch := sc.srv.state.getErrChan()
writeArg := writeDataPool.Get().(*writeData)
*writeArg = writeData{stream.id, data, endStream}
err := sc.writeFrameFromHandler(FrameWriteRequest{
@@ -1199,7 +1191,7 @@ func (sc *serverConn) writeDataFromHandler(stream *stream, data []byte, endStrea
return errStreamClosed
}
}
- errChanPool.Put(ch)
+ sc.srv.state.putErrChan(ch)
if frameWriteDone {
writeDataPool.Put(writeArg)
}
@@ -1513,7 +1505,7 @@ func (sc *serverConn) goAway(code ErrCode) {
func (sc *serverConn) shutDownIn(d time.Duration) {
sc.serveG.check()
- sc.shutdownTimer = sc.srv.afterFunc(d, sc.onShutdownTimer)
+ sc.shutdownTimer = time.AfterFunc(d, sc.onShutdownTimer)
}
func (sc *serverConn) resetStream(se StreamError) {
@@ -2118,7 +2110,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
// (in Go 1.8), though. That's a more sane option anyway.
if sc.hs.ReadTimeout > 0 {
sc.conn.SetReadDeadline(time.Time{})
- st.readDeadline = sc.srv.afterFunc(sc.hs.ReadTimeout, st.onReadTimeout)
+ st.readDeadline = time.AfterFunc(sc.hs.ReadTimeout, st.onReadTimeout)
}
return sc.scheduleHandler(id, rw, req, handler)
@@ -2216,7 +2208,7 @@ func (sc *serverConn) newStream(id, pusherID uint32, state streamState) *stream
st.flow.add(sc.initialStreamSendWindowSize)
st.inflow.init(sc.initialStreamRecvWindowSize)
if sc.hs.WriteTimeout > 0 {
- st.writeDeadline = sc.srv.afterFunc(sc.hs.WriteTimeout, st.onWriteTimeout)
+ st.writeDeadline = time.AfterFunc(sc.hs.WriteTimeout, st.onWriteTimeout)
}
sc.streams[id] = st
@@ -2405,7 +2397,6 @@ func (sc *serverConn) handlerDone() {
// Run on its own goroutine.
func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) {
- sc.srv.markNewGoroutine()
defer sc.sendServeMsg(handlerDoneMsg)
didPanic := true
defer func() {
@@ -2454,7 +2445,7 @@ func (sc *serverConn) writeHeaders(st *stream, headerData *writeResHeaders) erro
// waiting for this frame to be written, so an http.Flush mid-handler
// writes out the correct value of keys, before a handler later potentially
// mutates it.
- errc = errChanPool.Get().(chan error)
+ errc = sc.srv.state.getErrChan()
}
if err := sc.writeFrameFromHandler(FrameWriteRequest{
write: headerData,
@@ -2466,7 +2457,7 @@ func (sc *serverConn) writeHeaders(st *stream, headerData *writeResHeaders) erro
if errc != nil {
select {
case err := <-errc:
- errChanPool.Put(errc)
+ sc.srv.state.putErrChan(errc)
return err
case <-sc.doneServing:
return errClientDisconnected
@@ -2573,7 +2564,7 @@ func (b *requestBody) Read(p []byte) (n int, err error) {
if err == io.EOF {
b.sawEOF = true
}
- if b.conn == nil && inTests {
+ if b.conn == nil {
return
}
b.conn.noteBodyReadFromHandler(b.stream, n, err)
@@ -2702,7 +2693,7 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
var date string
if _, ok := rws.snapHeader["Date"]; !ok {
// TODO(bradfitz): be faster here, like net/http? measure.
- date = rws.conn.srv.now().UTC().Format(http.TimeFormat)
+ date = time.Now().UTC().Format(http.TimeFormat)
}
for _, v := range rws.snapHeader["Trailer"] {
@@ -2824,7 +2815,7 @@ func (rws *responseWriterState) promoteUndeclaredTrailers() {
func (w *responseWriter) SetReadDeadline(deadline time.Time) error {
st := w.rws.stream
- if !deadline.IsZero() && deadline.Before(w.rws.conn.srv.now()) {
+ if !deadline.IsZero() && deadline.Before(time.Now()) {
// If we're setting a deadline in the past, reset the stream immediately
// so writes after SetWriteDeadline returns will fail.
st.onReadTimeout()
@@ -2840,9 +2831,9 @@ func (w *responseWriter) SetReadDeadline(deadline time.Time) error {
if deadline.IsZero() {
st.readDeadline = nil
} else if st.readDeadline == nil {
- st.readDeadline = sc.srv.afterFunc(deadline.Sub(sc.srv.now()), st.onReadTimeout)
+ st.readDeadline = time.AfterFunc(deadline.Sub(time.Now()), st.onReadTimeout)
} else {
- st.readDeadline.Reset(deadline.Sub(sc.srv.now()))
+ st.readDeadline.Reset(deadline.Sub(time.Now()))
}
})
return nil
@@ -2850,7 +2841,7 @@ func (w *responseWriter) SetReadDeadline(deadline time.Time) error {
func (w *responseWriter) SetWriteDeadline(deadline time.Time) error {
st := w.rws.stream
- if !deadline.IsZero() && deadline.Before(w.rws.conn.srv.now()) {
+ if !deadline.IsZero() && deadline.Before(time.Now()) {
// If we're setting a deadline in the past, reset the stream immediately
// so writes after SetWriteDeadline returns will fail.
st.onWriteTimeout()
@@ -2866,9 +2857,9 @@ func (w *responseWriter) SetWriteDeadline(deadline time.Time) error {
if deadline.IsZero() {
st.writeDeadline = nil
} else if st.writeDeadline == nil {
- st.writeDeadline = sc.srv.afterFunc(deadline.Sub(sc.srv.now()), st.onWriteTimeout)
+ st.writeDeadline = time.AfterFunc(deadline.Sub(time.Now()), st.onWriteTimeout)
} else {
- st.writeDeadline.Reset(deadline.Sub(sc.srv.now()))
+ st.writeDeadline.Reset(deadline.Sub(time.Now()))
}
})
return nil
@@ -3147,7 +3138,7 @@ func (w *responseWriter) Push(target string, opts *http.PushOptions) error {
method: opts.Method,
url: u,
header: cloneHeader(opts.Header),
- done: errChanPool.Get().(chan error),
+ done: sc.srv.state.getErrChan(),
}
select {
@@ -3164,7 +3155,7 @@ func (w *responseWriter) Push(target string, opts *http.PushOptions) error {
case <-st.cw:
return errStreamClosed
case err := <-msg.done:
- errChanPool.Put(msg.done)
+ sc.srv.state.putErrChan(msg.done)
return err
}
}
diff --git a/vendor/golang.org/x/net/http2/timer.go b/vendor/golang.org/x/net/http2/timer.go
deleted file mode 100644
index 0b1c17b812..0000000000
--- a/vendor/golang.org/x/net/http2/timer.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2024 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-package http2
-
-import "time"
-
-// A timer is a time.Timer, as an interface which can be replaced in tests.
-type timer = interface {
- C() <-chan time.Time
- Reset(d time.Duration) bool
- Stop() bool
-}
-
-// timeTimer adapts a time.Timer to the timer interface.
-type timeTimer struct {
- *time.Timer
-}
-
-func (t timeTimer) C() <-chan time.Time { return t.Timer.C }
diff --git a/vendor/golang.org/x/net/http2/transport.go b/vendor/golang.org/x/net/http2/transport.go
index f26356b9cd..1965913e54 100644
--- a/vendor/golang.org/x/net/http2/transport.go
+++ b/vendor/golang.org/x/net/http2/transport.go
@@ -9,6 +9,7 @@ package http2
import (
"bufio"
"bytes"
+ "compress/flate"
"compress/gzip"
"context"
"crypto/rand"
@@ -193,50 +194,6 @@ type Transport struct {
type transportTestHooks struct {
newclientconn func(*ClientConn)
- group synctestGroupInterface
-}
-
-func (t *Transport) markNewGoroutine() {
- if t != nil && t.transportTestHooks != nil {
- t.transportTestHooks.group.Join()
- }
-}
-
-func (t *Transport) now() time.Time {
- if t != nil && t.transportTestHooks != nil {
- return t.transportTestHooks.group.Now()
- }
- return time.Now()
-}
-
-func (t *Transport) timeSince(when time.Time) time.Duration {
- if t != nil && t.transportTestHooks != nil {
- return t.now().Sub(when)
- }
- return time.Since(when)
-}
-
-// newTimer creates a new time.Timer, or a synthetic timer in tests.
-func (t *Transport) newTimer(d time.Duration) timer {
- if t.transportTestHooks != nil {
- return t.transportTestHooks.group.NewTimer(d)
- }
- return timeTimer{time.NewTimer(d)}
-}
-
-// afterFunc creates a new time.AfterFunc timer, or a synthetic timer in tests.
-func (t *Transport) afterFunc(d time.Duration, f func()) timer {
- if t.transportTestHooks != nil {
- return t.transportTestHooks.group.AfterFunc(d, f)
- }
- return timeTimer{time.AfterFunc(d, f)}
-}
-
-func (t *Transport) contextWithTimeout(ctx context.Context, d time.Duration) (context.Context, context.CancelFunc) {
- if t.transportTestHooks != nil {
- return t.transportTestHooks.group.ContextWithTimeout(ctx, d)
- }
- return context.WithTimeout(ctx, d)
}
func (t *Transport) maxHeaderListSize() uint32 {
@@ -366,7 +323,7 @@ type ClientConn struct {
readerErr error // set before readerDone is closed
idleTimeout time.Duration // or 0 for never
- idleTimer timer
+ idleTimer *time.Timer
mu sync.Mutex // guards following
cond *sync.Cond // hold mu; broadcast on flow/closed changes
@@ -399,6 +356,7 @@ type ClientConn struct {
readIdleTimeout time.Duration
pingTimeout time.Duration
extendedConnectAllowed bool
+ strictMaxConcurrentStreams bool
// rstStreamPingsBlocked works around an unfortunate gRPC behavior.
// gRPC strictly limits the number of PING frames that it will receive.
@@ -534,14 +492,12 @@ func (cs *clientStream) closeReqBodyLocked() {
cs.reqBodyClosed = make(chan struct{})
reqBodyClosed := cs.reqBodyClosed
go func() {
- cs.cc.t.markNewGoroutine()
cs.reqBody.Close()
close(reqBodyClosed)
}()
}
type stickyErrWriter struct {
- group synctestGroupInterface
conn net.Conn
timeout time.Duration
err *error
@@ -551,7 +507,7 @@ func (sew stickyErrWriter) Write(p []byte) (n int, err error) {
if *sew.err != nil {
return 0, *sew.err
}
- n, err = writeWithByteTimeout(sew.group, sew.conn, sew.timeout, p)
+ n, err = writeWithByteTimeout(sew.conn, sew.timeout, p)
*sew.err = err
return n, err
}
@@ -650,9 +606,9 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res
backoff := float64(uint(1) << (uint(retry) - 1))
backoff += backoff * (0.1 * mathrand.Float64())
d := time.Second * time.Duration(backoff)
- tm := t.newTimer(d)
+ tm := time.NewTimer(d)
select {
- case <-tm.C():
+ case <-tm.C:
t.vlogf("RoundTrip retrying after failure: %v", roundTripErr)
continue
case <-req.Context().Done():
@@ -699,6 +655,7 @@ var (
errClientConnUnusable = errors.New("http2: client conn not usable")
errClientConnNotEstablished = errors.New("http2: client conn could not be established")
errClientConnGotGoAway = errors.New("http2: Transport received Server's graceful shutdown GOAWAY")
+ errClientConnForceClosed = errors.New("http2: client connection force closed via ClientConn.Close")
)
// shouldRetryRequest is called by RoundTrip when a request fails to get
@@ -829,7 +786,8 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, erro
initialWindowSize: 65535, // spec default
initialStreamRecvWindowSize: conf.MaxUploadBufferPerStream,
maxConcurrentStreams: initialMaxConcurrentStreams, // "infinite", per spec. Use a smaller value until we have received server settings.
- peerMaxHeaderListSize: 0xffffffffffffffff, // "infinite", per spec. Use 2^64-1 instead.
+ strictMaxConcurrentStreams: conf.StrictMaxConcurrentRequests,
+ peerMaxHeaderListSize: 0xffffffffffffffff, // "infinite", per spec. Use 2^64-1 instead.
streams: make(map[uint32]*clientStream),
singleUse: singleUse,
seenSettingsChan: make(chan struct{}),
@@ -838,14 +796,11 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, erro
pingTimeout: conf.PingTimeout,
pings: make(map[[8]byte]chan struct{}),
reqHeaderMu: make(chan struct{}, 1),
- lastActive: t.now(),
+ lastActive: time.Now(),
}
- var group synctestGroupInterface
if t.transportTestHooks != nil {
- t.markNewGoroutine()
t.transportTestHooks.newclientconn(cc)
c = cc.tconn
- group = t.group
}
if VerboseLogs {
t.vlogf("http2: Transport creating client conn %p to %v", cc, c.RemoteAddr())
@@ -857,7 +812,6 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, erro
// TODO: adjust this writer size to account for frame size +
// MTU + crypto/tls record padding.
cc.bw = bufio.NewWriter(stickyErrWriter{
- group: group,
conn: c,
timeout: conf.WriteByteTimeout,
err: &cc.werr,
@@ -906,7 +860,7 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, erro
// Start the idle timer after the connection is fully initialized.
if d := t.idleConnTimeout(); d != 0 {
cc.idleTimeout = d
- cc.idleTimer = t.afterFunc(d, cc.onIdleTimeout)
+ cc.idleTimer = time.AfterFunc(d, cc.onIdleTimeout)
}
go cc.readLoop()
@@ -917,7 +871,7 @@ func (cc *ClientConn) healthCheck() {
pingTimeout := cc.pingTimeout
// We don't need to periodically ping in the health check, because the readLoop of ClientConn will
// trigger the healthCheck again if there is no frame received.
- ctx, cancel := cc.t.contextWithTimeout(context.Background(), pingTimeout)
+ ctx, cancel := context.WithTimeout(context.Background(), pingTimeout)
defer cancel()
cc.vlogf("http2: Transport sending health check")
err := cc.Ping(ctx)
@@ -1067,7 +1021,7 @@ func (cc *ClientConn) idleStateLocked() (st clientConnIdleState) {
return
}
var maxConcurrentOkay bool
- if cc.t.StrictMaxConcurrentStreams {
+ if cc.strictMaxConcurrentStreams {
// We'll tell the caller we can take a new request to
// prevent the caller from dialing a new TCP
// connection, but then we'll block later before
@@ -1120,7 +1074,7 @@ func (cc *ClientConn) tooIdleLocked() bool {
// times are compared based on their wall time. We don't want
// to reuse a connection that's been sitting idle during
// VM/laptop suspend if monotonic time was also frozen.
- return cc.idleTimeout != 0 && !cc.lastIdle.IsZero() && cc.t.timeSince(cc.lastIdle.Round(0)) > cc.idleTimeout
+ return cc.idleTimeout != 0 && !cc.lastIdle.IsZero() && time.Since(cc.lastIdle.Round(0)) > cc.idleTimeout
}
// onIdleTimeout is called from a time.AfterFunc goroutine. It will
@@ -1186,7 +1140,6 @@ func (cc *ClientConn) Shutdown(ctx context.Context) error {
done := make(chan struct{})
cancelled := false // guarded by cc.mu
go func() {
- cc.t.markNewGoroutine()
cc.mu.Lock()
defer cc.mu.Unlock()
for {
@@ -1257,8 +1210,7 @@ func (cc *ClientConn) closeForError(err error) {
//
// In-flight requests are interrupted. For a graceful shutdown, use Shutdown instead.
func (cc *ClientConn) Close() error {
- err := errors.New("http2: client connection force closed via ClientConn.Close")
- cc.closeForError(err)
+ cc.closeForError(errClientConnForceClosed)
return nil
}
@@ -1427,7 +1379,6 @@ func (cc *ClientConn) roundTrip(req *http.Request, streamf func(*clientStream))
//
// It sends the request and performs post-request cleanup (closing Request.Body, etc.).
func (cs *clientStream) doRequest(req *http.Request, streamf func(*clientStream)) {
- cs.cc.t.markNewGoroutine()
err := cs.writeRequest(req, streamf)
cs.cleanupWriteRequest(err)
}
@@ -1558,9 +1509,9 @@ func (cs *clientStream) writeRequest(req *http.Request, streamf func(*clientStre
var respHeaderTimer <-chan time.Time
var respHeaderRecv chan struct{}
if d := cc.responseHeaderTimeout(); d != 0 {
- timer := cc.t.newTimer(d)
+ timer := time.NewTimer(d)
defer timer.Stop()
- respHeaderTimer = timer.C()
+ respHeaderTimer = timer.C
respHeaderRecv = cs.respHeaderRecv
}
// Wait until the peer half-closes its end of the stream,
@@ -1753,7 +1704,7 @@ func (cc *ClientConn) awaitOpenSlotForStreamLocked(cs *clientStream) error {
// Return a fatal error which aborts the retry loop.
return errClientConnNotEstablished
}
- cc.lastActive = cc.t.now()
+ cc.lastActive = time.Now()
if cc.closed || !cc.canTakeNewRequestLocked() {
return errClientConnUnusable
}
@@ -2092,10 +2043,10 @@ func (cc *ClientConn) forgetStreamID(id uint32) {
if len(cc.streams) != slen-1 {
panic("forgetting unknown stream id")
}
- cc.lastActive = cc.t.now()
+ cc.lastActive = time.Now()
if len(cc.streams) == 0 && cc.idleTimer != nil {
cc.idleTimer.Reset(cc.idleTimeout)
- cc.lastIdle = cc.t.now()
+ cc.lastIdle = time.Now()
}
// Wake up writeRequestBody via clientStream.awaitFlowControl and
// wake up RoundTrip if there is a pending request.
@@ -2121,7 +2072,6 @@ type clientConnReadLoop struct {
// readLoop runs in its own goroutine and reads and dispatches frames.
func (cc *ClientConn) readLoop() {
- cc.t.markNewGoroutine()
rl := &clientConnReadLoop{cc: cc}
defer rl.cleanup()
cc.readerErr = rl.run()
@@ -2188,9 +2138,9 @@ func (rl *clientConnReadLoop) cleanup() {
if cc.idleTimeout > 0 && unusedWaitTime > cc.idleTimeout {
unusedWaitTime = cc.idleTimeout
}
- idleTime := cc.t.now().Sub(cc.lastActive)
+ idleTime := time.Now().Sub(cc.lastActive)
if atomic.LoadUint32(&cc.atomicReused) == 0 && idleTime < unusedWaitTime && !cc.closedOnIdle {
- cc.idleTimer = cc.t.afterFunc(unusedWaitTime-idleTime, func() {
+ cc.idleTimer = time.AfterFunc(unusedWaitTime-idleTime, func() {
cc.t.connPool().MarkDead(cc)
})
} else {
@@ -2250,9 +2200,9 @@ func (rl *clientConnReadLoop) run() error {
cc := rl.cc
gotSettings := false
readIdleTimeout := cc.readIdleTimeout
- var t timer
+ var t *time.Timer
if readIdleTimeout != 0 {
- t = cc.t.afterFunc(readIdleTimeout, cc.healthCheck)
+ t = time.AfterFunc(readIdleTimeout, cc.healthCheck)
}
for {
f, err := cc.fr.ReadFrame()
@@ -2998,7 +2948,6 @@ func (cc *ClientConn) Ping(ctx context.Context) error {
var pingError error
errc := make(chan struct{})
go func() {
- cc.t.markNewGoroutine()
cc.wmu.Lock()
defer cc.wmu.Unlock()
if pingError = cc.fr.WritePing(false, p); pingError != nil {
@@ -3128,35 +3077,102 @@ type erringRoundTripper struct{ err error }
func (rt erringRoundTripper) RoundTripErr() error { return rt.err }
func (rt erringRoundTripper) RoundTrip(*http.Request) (*http.Response, error) { return nil, rt.err }
+var errConcurrentReadOnResBody = errors.New("http2: concurrent read on response body")
+
// gzipReader wraps a response body so it can lazily
-// call gzip.NewReader on the first call to Read
+// get gzip.Reader from the pool on the first call to Read.
+// After Close is called it puts gzip.Reader to the pool immediately
+// if there is no Read in progress or later when Read completes.
type gzipReader struct {
_ incomparable
body io.ReadCloser // underlying Response.Body
- zr *gzip.Reader // lazily-initialized gzip reader
- zerr error // sticky error
+ mu sync.Mutex // guards zr and zerr
+ zr *gzip.Reader // stores gzip reader from the pool between reads
+ zerr error // sticky gzip reader init error or sentinel value to detect concurrent read and read after close
}
-func (gz *gzipReader) Read(p []byte) (n int, err error) {
+type eofReader struct{}
+
+func (eofReader) Read([]byte) (int, error) { return 0, io.EOF }
+func (eofReader) ReadByte() (byte, error) { return 0, io.EOF }
+
+var gzipPool = sync.Pool{New: func() any { return new(gzip.Reader) }}
+
+// gzipPoolGet gets a gzip.Reader from the pool and resets it to read from r.
+func gzipPoolGet(r io.Reader) (*gzip.Reader, error) {
+ zr := gzipPool.Get().(*gzip.Reader)
+ if err := zr.Reset(r); err != nil {
+ gzipPoolPut(zr)
+ return nil, err
+ }
+ return zr, nil
+}
+
+// gzipPoolPut puts a gzip.Reader back into the pool.
+func gzipPoolPut(zr *gzip.Reader) {
+ // Reset will allocate bufio.Reader if we pass it anything
+ // other than a flate.Reader, so ensure that it's getting one.
+ var r flate.Reader = eofReader{}
+ zr.Reset(r)
+ gzipPool.Put(zr)
+}
+
+// acquire returns a gzip.Reader for reading response body.
+// The reader must be released after use.
+func (gz *gzipReader) acquire() (*gzip.Reader, error) {
+ gz.mu.Lock()
+ defer gz.mu.Unlock()
if gz.zerr != nil {
- return 0, gz.zerr
+ return nil, gz.zerr
}
if gz.zr == nil {
- gz.zr, err = gzip.NewReader(gz.body)
- if err != nil {
- gz.zerr = err
- return 0, err
+ gz.zr, gz.zerr = gzipPoolGet(gz.body)
+ if gz.zerr != nil {
+ return nil, gz.zerr
}
}
- return gz.zr.Read(p)
+ ret := gz.zr
+ gz.zr, gz.zerr = nil, errConcurrentReadOnResBody
+ return ret, nil
}
-func (gz *gzipReader) Close() error {
- if err := gz.body.Close(); err != nil {
- return err
+// release returns the gzip.Reader to the pool if Close was called during Read.
+func (gz *gzipReader) release(zr *gzip.Reader) {
+ gz.mu.Lock()
+ defer gz.mu.Unlock()
+ if gz.zerr == errConcurrentReadOnResBody {
+ gz.zr, gz.zerr = zr, nil
+ } else { // fs.ErrClosed
+ gzipPoolPut(zr)
+ }
+}
+
+// close returns the gzip.Reader to the pool immediately or
+// signals release to do so after Read completes.
+func (gz *gzipReader) close() {
+ gz.mu.Lock()
+ defer gz.mu.Unlock()
+ if gz.zerr == nil && gz.zr != nil {
+ gzipPoolPut(gz.zr)
+ gz.zr = nil
}
gz.zerr = fs.ErrClosed
- return nil
+}
+
+func (gz *gzipReader) Read(p []byte) (n int, err error) {
+ zr, err := gz.acquire()
+ if err != nil {
+ return 0, err
+ }
+ defer gz.release(zr)
+
+ return zr.Read(p)
+}
+
+func (gz *gzipReader) Close() error {
+ gz.close()
+
+ return gz.body.Close()
}
type errorReader struct{ err error }
@@ -3228,7 +3244,7 @@ func traceGotConn(req *http.Request, cc *ClientConn, reused bool) {
cc.mu.Lock()
ci.WasIdle = len(cc.streams) == 0 && reused
if ci.WasIdle && !cc.lastActive.IsZero() {
- ci.IdleTime = cc.t.timeSince(cc.lastActive)
+ ci.IdleTime = time.Since(cc.lastActive)
}
cc.mu.Unlock()
diff --git a/vendor/golang.org/x/net/http2/writesched.go b/vendor/golang.org/x/net/http2/writesched.go
index cc893adc29..7de27be525 100644
--- a/vendor/golang.org/x/net/http2/writesched.go
+++ b/vendor/golang.org/x/net/http2/writesched.go
@@ -42,6 +42,8 @@ type OpenStreamOptions struct {
// PusherID is zero if the stream was initiated by the client. Otherwise,
// PusherID names the stream that pushed the newly opened stream.
PusherID uint32
+ // priority is used to set the priority of the newly opened stream.
+ priority PriorityParam
}
// FrameWriteRequest is a request to write a frame.
@@ -183,45 +185,75 @@ func (wr *FrameWriteRequest) replyToWriter(err error) {
}
// writeQueue is used by implementations of WriteScheduler.
+//
+// Each writeQueue contains a queue of FrameWriteRequests, meant to store all
+// FrameWriteRequests associated with a given stream. This is implemented as a
+// two-stage queue: currQueue[currPos:] and nextQueue. Removing an item is done
+// by incrementing currPos of currQueue. Adding an item is done by appending it
+// to the nextQueue. If currQueue is empty when trying to remove an item, we
+// can swap currQueue and nextQueue to remedy the situation.
+// This two-stage queue is analogous to the use of two lists in Okasaki's
+// purely functional queue but without the overhead of reversing the list when
+// swapping stages.
+//
+// writeQueue also contains prev and next, this can be used by implementations
+// of WriteScheduler to construct data structures that represent the order of
+// writing between different streams (e.g. circular linked list).
type writeQueue struct {
- s []FrameWriteRequest
+ currQueue []FrameWriteRequest
+ nextQueue []FrameWriteRequest
+ currPos int
+
prev, next *writeQueue
}
-func (q *writeQueue) empty() bool { return len(q.s) == 0 }
+func (q *writeQueue) empty() bool {
+ return (len(q.currQueue) - q.currPos + len(q.nextQueue)) == 0
+}
func (q *writeQueue) push(wr FrameWriteRequest) {
- q.s = append(q.s, wr)
+ q.nextQueue = append(q.nextQueue, wr)
}
func (q *writeQueue) shift() FrameWriteRequest {
- if len(q.s) == 0 {
+ if q.empty() {
panic("invalid use of queue")
}
- wr := q.s[0]
- // TODO: less copy-happy queue.
- copy(q.s, q.s[1:])
- q.s[len(q.s)-1] = FrameWriteRequest{}
- q.s = q.s[:len(q.s)-1]
+ if q.currPos >= len(q.currQueue) {
+ q.currQueue, q.currPos, q.nextQueue = q.nextQueue, 0, q.currQueue[:0]
+ }
+ wr := q.currQueue[q.currPos]
+ q.currQueue[q.currPos] = FrameWriteRequest{}
+ q.currPos++
return wr
}
+func (q *writeQueue) peek() *FrameWriteRequest {
+ if q.currPos < len(q.currQueue) {
+ return &q.currQueue[q.currPos]
+ }
+ if len(q.nextQueue) > 0 {
+ return &q.nextQueue[0]
+ }
+ return nil
+}
+
// consume consumes up to n bytes from q.s[0]. If the frame is
// entirely consumed, it is removed from the queue. If the frame
// is partially consumed, the frame is kept with the consumed
// bytes removed. Returns true iff any bytes were consumed.
func (q *writeQueue) consume(n int32) (FrameWriteRequest, bool) {
- if len(q.s) == 0 {
+ if q.empty() {
return FrameWriteRequest{}, false
}
- consumed, rest, numresult := q.s[0].Consume(n)
+ consumed, rest, numresult := q.peek().Consume(n)
switch numresult {
case 0:
return FrameWriteRequest{}, false
case 1:
q.shift()
case 2:
- q.s[0] = rest
+ *q.peek() = rest
}
return consumed, true
}
@@ -230,10 +262,15 @@ type writeQueuePool []*writeQueue
// put inserts an unused writeQueue into the pool.
func (p *writeQueuePool) put(q *writeQueue) {
- for i := range q.s {
- q.s[i] = FrameWriteRequest{}
+ for i := range q.currQueue {
+ q.currQueue[i] = FrameWriteRequest{}
+ }
+ for i := range q.nextQueue {
+ q.nextQueue[i] = FrameWriteRequest{}
}
- q.s = q.s[:0]
+ q.currQueue = q.currQueue[:0]
+ q.nextQueue = q.nextQueue[:0]
+ q.currPos = 0
*p = append(*p, q)
}
diff --git a/etcd/vendor/golang.org/x/net/http2/writesched_priority.go b/vendor/golang.org/x/net/http2/writesched_priority_rfc7540.go
similarity index 77%
rename from etcd/vendor/golang.org/x/net/http2/writesched_priority.go
rename to vendor/golang.org/x/net/http2/writesched_priority_rfc7540.go
index f6783339d1..4e33c29a24 100644
--- a/etcd/vendor/golang.org/x/net/http2/writesched_priority.go
+++ b/vendor/golang.org/x/net/http2/writesched_priority_rfc7540.go
@@ -11,7 +11,7 @@ import (
)
// RFC 7540, Section 5.3.5: the default weight is 16.
-const priorityDefaultWeight = 15 // 16 = 15 + 1
+const priorityDefaultWeightRFC7540 = 15 // 16 = 15 + 1
// PriorityWriteSchedulerConfig configures a priorityWriteScheduler.
type PriorityWriteSchedulerConfig struct {
@@ -66,8 +66,8 @@ func NewPriorityWriteScheduler(cfg *PriorityWriteSchedulerConfig) WriteScheduler
}
}
- ws := &priorityWriteScheduler{
- nodes: make(map[uint32]*priorityNode),
+ ws := &priorityWriteSchedulerRFC7540{
+ nodes: make(map[uint32]*priorityNodeRFC7540),
maxClosedNodesInTree: cfg.MaxClosedNodesInTree,
maxIdleNodesInTree: cfg.MaxIdleNodesInTree,
enableWriteThrottle: cfg.ThrottleOutOfOrderWrites,
@@ -81,32 +81,32 @@ func NewPriorityWriteScheduler(cfg *PriorityWriteSchedulerConfig) WriteScheduler
return ws
}
-type priorityNodeState int
+type priorityNodeStateRFC7540 int
const (
- priorityNodeOpen priorityNodeState = iota
- priorityNodeClosed
- priorityNodeIdle
+ priorityNodeOpenRFC7540 priorityNodeStateRFC7540 = iota
+ priorityNodeClosedRFC7540
+ priorityNodeIdleRFC7540
)
-// priorityNode is a node in an HTTP/2 priority tree.
+// priorityNodeRFC7540 is a node in an HTTP/2 priority tree.
// Each node is associated with a single stream ID.
// See RFC 7540, Section 5.3.
-type priorityNode struct {
- q writeQueue // queue of pending frames to write
- id uint32 // id of the stream, or 0 for the root of the tree
- weight uint8 // the actual weight is weight+1, so the value is in [1,256]
- state priorityNodeState // open | closed | idle
- bytes int64 // number of bytes written by this node, or 0 if closed
- subtreeBytes int64 // sum(node.bytes) of all nodes in this subtree
+type priorityNodeRFC7540 struct {
+ q writeQueue // queue of pending frames to write
+ id uint32 // id of the stream, or 0 for the root of the tree
+ weight uint8 // the actual weight is weight+1, so the value is in [1,256]
+ state priorityNodeStateRFC7540 // open | closed | idle
+ bytes int64 // number of bytes written by this node, or 0 if closed
+ subtreeBytes int64 // sum(node.bytes) of all nodes in this subtree
// These links form the priority tree.
- parent *priorityNode
- kids *priorityNode // start of the kids list
- prev, next *priorityNode // doubly-linked list of siblings
+ parent *priorityNodeRFC7540
+ kids *priorityNodeRFC7540 // start of the kids list
+ prev, next *priorityNodeRFC7540 // doubly-linked list of siblings
}
-func (n *priorityNode) setParent(parent *priorityNode) {
+func (n *priorityNodeRFC7540) setParent(parent *priorityNodeRFC7540) {
if n == parent {
panic("setParent to self")
}
@@ -141,7 +141,7 @@ func (n *priorityNode) setParent(parent *priorityNode) {
}
}
-func (n *priorityNode) addBytes(b int64) {
+func (n *priorityNodeRFC7540) addBytes(b int64) {
n.bytes += b
for ; n != nil; n = n.parent {
n.subtreeBytes += b
@@ -154,7 +154,7 @@ func (n *priorityNode) addBytes(b int64) {
//
// f(n, openParent) takes two arguments: the node to visit, n, and a bool that is true
// if any ancestor p of n is still open (ignoring the root node).
-func (n *priorityNode) walkReadyInOrder(openParent bool, tmp *[]*priorityNode, f func(*priorityNode, bool) bool) bool {
+func (n *priorityNodeRFC7540) walkReadyInOrder(openParent bool, tmp *[]*priorityNodeRFC7540, f func(*priorityNodeRFC7540, bool) bool) bool {
if !n.q.empty() && f(n, openParent) {
return true
}
@@ -165,7 +165,7 @@ func (n *priorityNode) walkReadyInOrder(openParent bool, tmp *[]*priorityNode, f
// Don't consider the root "open" when updating openParent since
// we can't send data frames on the root stream (only control frames).
if n.id != 0 {
- openParent = openParent || (n.state == priorityNodeOpen)
+ openParent = openParent || (n.state == priorityNodeOpenRFC7540)
}
// Common case: only one kid or all kids have the same weight.
@@ -195,7 +195,7 @@ func (n *priorityNode) walkReadyInOrder(openParent bool, tmp *[]*priorityNode, f
*tmp = append(*tmp, n.kids)
n.kids.setParent(nil)
}
- sort.Sort(sortPriorityNodeSiblings(*tmp))
+ sort.Sort(sortPriorityNodeSiblingsRFC7540(*tmp))
for i := len(*tmp) - 1; i >= 0; i-- {
(*tmp)[i].setParent(n) // setParent inserts at the head of n.kids
}
@@ -207,15 +207,15 @@ func (n *priorityNode) walkReadyInOrder(openParent bool, tmp *[]*priorityNode, f
return false
}
-type sortPriorityNodeSiblings []*priorityNode
+type sortPriorityNodeSiblingsRFC7540 []*priorityNodeRFC7540
-func (z sortPriorityNodeSiblings) Len() int { return len(z) }
-func (z sortPriorityNodeSiblings) Swap(i, k int) { z[i], z[k] = z[k], z[i] }
-func (z sortPriorityNodeSiblings) Less(i, k int) bool {
+func (z sortPriorityNodeSiblingsRFC7540) Len() int { return len(z) }
+func (z sortPriorityNodeSiblingsRFC7540) Swap(i, k int) { z[i], z[k] = z[k], z[i] }
+func (z sortPriorityNodeSiblingsRFC7540) Less(i, k int) bool {
// Prefer the subtree that has sent fewer bytes relative to its weight.
// See sections 5.3.2 and 5.3.4.
- wi, bi := float64(z[i].weight+1), float64(z[i].subtreeBytes)
- wk, bk := float64(z[k].weight+1), float64(z[k].subtreeBytes)
+ wi, bi := float64(z[i].weight)+1, float64(z[i].subtreeBytes)
+ wk, bk := float64(z[k].weight)+1, float64(z[k].subtreeBytes)
if bi == 0 && bk == 0 {
return wi >= wk
}
@@ -225,13 +225,13 @@ func (z sortPriorityNodeSiblings) Less(i, k int) bool {
return bi/bk <= wi/wk
}
-type priorityWriteScheduler struct {
+type priorityWriteSchedulerRFC7540 struct {
// root is the root of the priority tree, where root.id = 0.
// The root queues control frames that are not associated with any stream.
- root priorityNode
+ root priorityNodeRFC7540
// nodes maps stream ids to priority tree nodes.
- nodes map[uint32]*priorityNode
+ nodes map[uint32]*priorityNodeRFC7540
// maxID is the maximum stream id in nodes.
maxID uint32
@@ -239,7 +239,7 @@ type priorityWriteScheduler struct {
// lists of nodes that have been closed or are idle, but are kept in
// the tree for improved prioritization. When the lengths exceed either
// maxClosedNodesInTree or maxIdleNodesInTree, old nodes are discarded.
- closedNodes, idleNodes []*priorityNode
+ closedNodes, idleNodes []*priorityNodeRFC7540
// From the config.
maxClosedNodesInTree int
@@ -248,19 +248,19 @@ type priorityWriteScheduler struct {
enableWriteThrottle bool
// tmp is scratch space for priorityNode.walkReadyInOrder to reduce allocations.
- tmp []*priorityNode
+ tmp []*priorityNodeRFC7540
// pool of empty queues for reuse.
queuePool writeQueuePool
}
-func (ws *priorityWriteScheduler) OpenStream(streamID uint32, options OpenStreamOptions) {
+func (ws *priorityWriteSchedulerRFC7540) OpenStream(streamID uint32, options OpenStreamOptions) {
// The stream may be currently idle but cannot be opened or closed.
if curr := ws.nodes[streamID]; curr != nil {
- if curr.state != priorityNodeIdle {
+ if curr.state != priorityNodeIdleRFC7540 {
panic(fmt.Sprintf("stream %d already opened", streamID))
}
- curr.state = priorityNodeOpen
+ curr.state = priorityNodeOpenRFC7540
return
}
@@ -272,11 +272,11 @@ func (ws *priorityWriteScheduler) OpenStream(streamID uint32, options OpenStream
if parent == nil {
parent = &ws.root
}
- n := &priorityNode{
+ n := &priorityNodeRFC7540{
q: *ws.queuePool.get(),
id: streamID,
- weight: priorityDefaultWeight,
- state: priorityNodeOpen,
+ weight: priorityDefaultWeightRFC7540,
+ state: priorityNodeOpenRFC7540,
}
n.setParent(parent)
ws.nodes[streamID] = n
@@ -285,24 +285,23 @@ func (ws *priorityWriteScheduler) OpenStream(streamID uint32, options OpenStream
}
}
-func (ws *priorityWriteScheduler) CloseStream(streamID uint32) {
+func (ws *priorityWriteSchedulerRFC7540) CloseStream(streamID uint32) {
if streamID == 0 {
panic("violation of WriteScheduler interface: cannot close stream 0")
}
if ws.nodes[streamID] == nil {
panic(fmt.Sprintf("violation of WriteScheduler interface: unknown stream %d", streamID))
}
- if ws.nodes[streamID].state != priorityNodeOpen {
+ if ws.nodes[streamID].state != priorityNodeOpenRFC7540 {
panic(fmt.Sprintf("violation of WriteScheduler interface: stream %d already closed", streamID))
}
n := ws.nodes[streamID]
- n.state = priorityNodeClosed
+ n.state = priorityNodeClosedRFC7540
n.addBytes(-n.bytes)
q := n.q
ws.queuePool.put(&q)
- n.q.s = nil
if ws.maxClosedNodesInTree > 0 {
ws.addClosedOrIdleNode(&ws.closedNodes, ws.maxClosedNodesInTree, n)
} else {
@@ -310,7 +309,7 @@ func (ws *priorityWriteScheduler) CloseStream(streamID uint32) {
}
}
-func (ws *priorityWriteScheduler) AdjustStream(streamID uint32, priority PriorityParam) {
+func (ws *priorityWriteSchedulerRFC7540) AdjustStream(streamID uint32, priority PriorityParam) {
if streamID == 0 {
panic("adjustPriority on root")
}
@@ -324,11 +323,11 @@ func (ws *priorityWriteScheduler) AdjustStream(streamID uint32, priority Priorit
return
}
ws.maxID = streamID
- n = &priorityNode{
+ n = &priorityNodeRFC7540{
q: *ws.queuePool.get(),
id: streamID,
- weight: priorityDefaultWeight,
- state: priorityNodeIdle,
+ weight: priorityDefaultWeightRFC7540,
+ state: priorityNodeIdleRFC7540,
}
n.setParent(&ws.root)
ws.nodes[streamID] = n
@@ -340,7 +339,7 @@ func (ws *priorityWriteScheduler) AdjustStream(streamID uint32, priority Priorit
parent := ws.nodes[priority.StreamDep]
if parent == nil {
n.setParent(&ws.root)
- n.weight = priorityDefaultWeight
+ n.weight = priorityDefaultWeightRFC7540
return
}
@@ -381,8 +380,8 @@ func (ws *priorityWriteScheduler) AdjustStream(streamID uint32, priority Priorit
n.weight = priority.Weight
}
-func (ws *priorityWriteScheduler) Push(wr FrameWriteRequest) {
- var n *priorityNode
+func (ws *priorityWriteSchedulerRFC7540) Push(wr FrameWriteRequest) {
+ var n *priorityNodeRFC7540
if wr.isControl() {
n = &ws.root
} else {
@@ -401,8 +400,8 @@ func (ws *priorityWriteScheduler) Push(wr FrameWriteRequest) {
n.q.push(wr)
}
-func (ws *priorityWriteScheduler) Pop() (wr FrameWriteRequest, ok bool) {
- ws.root.walkReadyInOrder(false, &ws.tmp, func(n *priorityNode, openParent bool) bool {
+func (ws *priorityWriteSchedulerRFC7540) Pop() (wr FrameWriteRequest, ok bool) {
+ ws.root.walkReadyInOrder(false, &ws.tmp, func(n *priorityNodeRFC7540, openParent bool) bool {
limit := int32(math.MaxInt32)
if openParent {
limit = ws.writeThrottleLimit
@@ -428,7 +427,7 @@ func (ws *priorityWriteScheduler) Pop() (wr FrameWriteRequest, ok bool) {
return wr, ok
}
-func (ws *priorityWriteScheduler) addClosedOrIdleNode(list *[]*priorityNode, maxSize int, n *priorityNode) {
+func (ws *priorityWriteSchedulerRFC7540) addClosedOrIdleNode(list *[]*priorityNodeRFC7540, maxSize int, n *priorityNodeRFC7540) {
if maxSize == 0 {
return
}
@@ -442,7 +441,7 @@ func (ws *priorityWriteScheduler) addClosedOrIdleNode(list *[]*priorityNode, max
*list = append(*list, n)
}
-func (ws *priorityWriteScheduler) removeNode(n *priorityNode) {
+func (ws *priorityWriteSchedulerRFC7540) removeNode(n *priorityNodeRFC7540) {
for n.kids != nil {
n.kids.setParent(n.parent)
}
diff --git a/vendor/golang.org/x/net/http2/writesched_priority_rfc9218.go b/vendor/golang.org/x/net/http2/writesched_priority_rfc9218.go
new file mode 100644
index 0000000000..cb4cadc32d
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/writesched_priority_rfc9218.go
@@ -0,0 +1,209 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http2
+
+import (
+ "fmt"
+ "math"
+)
+
+type streamMetadata struct {
+ location *writeQueue
+ priority PriorityParam
+}
+
+type priorityWriteSchedulerRFC9218 struct {
+ // control contains control frames (SETTINGS, PING, etc.).
+ control writeQueue
+
+ // heads contain the head of a circular list of streams.
+ // We put these heads within a nested array that represents urgency and
+ // incremental, as defined in
+ // https://www.rfc-editor.org/rfc/rfc9218.html#name-priority-parameters.
+ // 8 represents u=0 up to u=7, and 2 represents i=false and i=true.
+ heads [8][2]*writeQueue
+
+ // streams contains a mapping between each stream ID and their metadata, so
+ // we can quickly locate them when needing to, for example, adjust their
+ // priority.
+ streams map[uint32]streamMetadata
+
+ // queuePool are empty queues for reuse.
+ queuePool writeQueuePool
+
+ // prioritizeIncremental is used to determine whether we should prioritize
+ // incremental streams or not, when urgency is the same in a given Pop()
+ // call.
+ prioritizeIncremental bool
+}
+
+func newPriorityWriteSchedulerRFC9218() WriteScheduler {
+ ws := &priorityWriteSchedulerRFC9218{
+ streams: make(map[uint32]streamMetadata),
+ }
+ return ws
+}
+
+func (ws *priorityWriteSchedulerRFC9218) OpenStream(streamID uint32, opt OpenStreamOptions) {
+ if ws.streams[streamID].location != nil {
+ panic(fmt.Errorf("stream %d already opened", streamID))
+ }
+ q := ws.queuePool.get()
+ ws.streams[streamID] = streamMetadata{
+ location: q,
+ priority: opt.priority,
+ }
+
+ u, i := opt.priority.urgency, opt.priority.incremental
+ if ws.heads[u][i] == nil {
+ ws.heads[u][i] = q
+ q.next = q
+ q.prev = q
+ } else {
+ // Queues are stored in a ring.
+ // Insert the new stream before ws.head, putting it at the end of the list.
+ q.prev = ws.heads[u][i].prev
+ q.next = ws.heads[u][i]
+ q.prev.next = q
+ q.next.prev = q
+ }
+}
+
+func (ws *priorityWriteSchedulerRFC9218) CloseStream(streamID uint32) {
+ metadata := ws.streams[streamID]
+ q, u, i := metadata.location, metadata.priority.urgency, metadata.priority.incremental
+ if q == nil {
+ return
+ }
+ if q.next == q {
+ // This was the only open stream.
+ ws.heads[u][i] = nil
+ } else {
+ q.prev.next = q.next
+ q.next.prev = q.prev
+ if ws.heads[u][i] == q {
+ ws.heads[u][i] = q.next
+ }
+ }
+ delete(ws.streams, streamID)
+ ws.queuePool.put(q)
+}
+
+func (ws *priorityWriteSchedulerRFC9218) AdjustStream(streamID uint32, priority PriorityParam) {
+ metadata := ws.streams[streamID]
+ q, u, i := metadata.location, metadata.priority.urgency, metadata.priority.incremental
+ if q == nil {
+ return
+ }
+
+ // Remove stream from current location.
+ if q.next == q {
+ // This was the only open stream.
+ ws.heads[u][i] = nil
+ } else {
+ q.prev.next = q.next
+ q.next.prev = q.prev
+ if ws.heads[u][i] == q {
+ ws.heads[u][i] = q.next
+ }
+ }
+
+ // Insert stream to the new queue.
+ u, i = priority.urgency, priority.incremental
+ if ws.heads[u][i] == nil {
+ ws.heads[u][i] = q
+ q.next = q
+ q.prev = q
+ } else {
+ // Queues are stored in a ring.
+ // Insert the new stream before ws.head, putting it at the end of the list.
+ q.prev = ws.heads[u][i].prev
+ q.next = ws.heads[u][i]
+ q.prev.next = q
+ q.next.prev = q
+ }
+
+ // Update the metadata.
+ ws.streams[streamID] = streamMetadata{
+ location: q,
+ priority: priority,
+ }
+}
+
+func (ws *priorityWriteSchedulerRFC9218) Push(wr FrameWriteRequest) {
+ if wr.isControl() {
+ ws.control.push(wr)
+ return
+ }
+ q := ws.streams[wr.StreamID()].location
+ if q == nil {
+ // This is a closed stream.
+ // wr should not be a HEADERS or DATA frame.
+ // We push the request onto the control queue.
+ if wr.DataSize() > 0 {
+ panic("add DATA on non-open stream")
+ }
+ ws.control.push(wr)
+ return
+ }
+ q.push(wr)
+}
+
+func (ws *priorityWriteSchedulerRFC9218) Pop() (FrameWriteRequest, bool) {
+ // Control and RST_STREAM frames first.
+ if !ws.control.empty() {
+ return ws.control.shift(), true
+ }
+
+ // On the next Pop(), we want to prioritize incremental if we prioritized
+ // non-incremental request of the same urgency this time. Vice-versa.
+ // i.e. when there are incremental and non-incremental requests at the same
+ // priority, we give 50% of our bandwidth to the incremental ones in
+ // aggregate and 50% to the first non-incremental one (since
+ // non-incremental streams do not use round-robin writes).
+ ws.prioritizeIncremental = !ws.prioritizeIncremental
+
+ // Always prioritize lowest u (i.e. highest urgency level).
+ for u := range ws.heads {
+ for i := range ws.heads[u] {
+ // When we want to prioritize incremental, we try to pop i=true
+ // first before i=false when u is the same.
+ if ws.prioritizeIncremental {
+ i = (i + 1) % 2
+ }
+ q := ws.heads[u][i]
+ if q == nil {
+ continue
+ }
+ for {
+ if wr, ok := q.consume(math.MaxInt32); ok {
+ if i == 1 {
+ // For incremental streams, we update head to q.next so
+ // we can round-robin between multiple streams that can
+ // immediately benefit from partial writes.
+ ws.heads[u][i] = q.next
+ } else {
+ // For non-incremental streams, we try to finish one to
+ // completion rather than doing round-robin. However,
+ // we update head here so that if q.consume() is !ok
+ // (e.g. the stream has no more frame to consume), head
+ // is updated to the next q that has frames to consume
+ // on future iterations. This way, we do not prioritize
+ // writing to unavailable stream on next Pop() calls,
+ // preventing head-of-line blocking.
+ ws.heads[u][i] = q
+ }
+ return wr, true
+ }
+ q = q.next
+ if q == ws.heads[u][i] {
+ break
+ }
+ }
+
+ }
+ }
+ return FrameWriteRequest{}, false
+}
diff --git a/vendor/golang.org/x/net/http2/writesched_roundrobin.go b/vendor/golang.org/x/net/http2/writesched_roundrobin.go
index 54fe86322d..737cff9ecb 100644
--- a/vendor/golang.org/x/net/http2/writesched_roundrobin.go
+++ b/vendor/golang.org/x/net/http2/writesched_roundrobin.go
@@ -25,7 +25,7 @@ type roundRobinWriteScheduler struct {
}
// newRoundRobinWriteScheduler constructs a new write scheduler.
-// The round robin scheduler priorizes control frames
+// The round robin scheduler prioritizes control frames
// like SETTINGS and PING over DATA frames.
// When there are no control frames to send, it performs a round-robin
// selection from the ready streams.
diff --git a/vendor/golang.org/x/net/internal/httpcommon/request.go b/vendor/golang.org/x/net/internal/httpcommon/request.go
index 4b70553179..1e10f89ebf 100644
--- a/vendor/golang.org/x/net/internal/httpcommon/request.go
+++ b/vendor/golang.org/x/net/internal/httpcommon/request.go
@@ -51,7 +51,7 @@ type EncodeHeadersParam struct {
DefaultUserAgent string
}
-// EncodeHeadersParam is the result of EncodeHeaders.
+// EncodeHeadersResult is the result of EncodeHeaders.
type EncodeHeadersResult struct {
HasBody bool
HasTrailers bool
@@ -399,7 +399,7 @@ type ServerRequestResult struct {
// If the request should be rejected, this is a short string suitable for passing
// to the http2 package's CountError function.
- // It might be a bit odd to return errors this way rather than returing an error,
+ // It might be a bit odd to return errors this way rather than returning an error,
// but this ensures we don't forget to include a CountError reason.
InvalidReason string
}
diff --git a/vendor/golang.org/x/net/internal/socks/socks.go b/vendor/golang.org/x/net/internal/socks/socks.go
index 84fcc32b63..8eedb84cec 100644
--- a/vendor/golang.org/x/net/internal/socks/socks.go
+++ b/vendor/golang.org/x/net/internal/socks/socks.go
@@ -297,7 +297,7 @@ func (up *UsernamePassword) Authenticate(ctx context.Context, rw io.ReadWriter,
b = append(b, up.Username...)
b = append(b, byte(len(up.Password)))
b = append(b, up.Password...)
- // TODO(mikio): handle IO deadlines and cancelation if
+ // TODO(mikio): handle IO deadlines and cancellation if
// necessary
if _, err := rw.Write(b); err != nil {
return err
diff --git a/vendor/golang.org/x/sync/errgroup/errgroup.go b/vendor/golang.org/x/sync/errgroup/errgroup.go
index 1d8cffae8c..2f45dbc86e 100644
--- a/vendor/golang.org/x/sync/errgroup/errgroup.go
+++ b/vendor/golang.org/x/sync/errgroup/errgroup.go
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// Package errgroup provides synchronization, error propagation, and Context
-// cancelation for groups of goroutines working on subtasks of a common task.
+// cancellation for groups of goroutines working on subtasks of a common task.
//
// [errgroup.Group] is related to [sync.WaitGroup] but adds handling of tasks
// returning errors.
diff --git a/vendor/golang.org/x/sys/cpu/cpu.go b/vendor/golang.org/x/sys/cpu/cpu.go
index 63541994ef..34c9ae76ef 100644
--- a/vendor/golang.org/x/sys/cpu/cpu.go
+++ b/vendor/golang.org/x/sys/cpu/cpu.go
@@ -92,6 +92,9 @@ var ARM64 struct {
HasSHA2 bool // SHA2 hardware implementation
HasCRC32 bool // CRC32 hardware implementation
HasATOMICS bool // Atomic memory operation instruction set
+ HasHPDS bool // Hierarchical permission disables in translations tables
+ HasLOR bool // Limited ordering regions
+ HasPAN bool // Privileged access never
HasFPHP bool // Half precision floating-point instruction set
HasASIMDHP bool // Advanced SIMD half precision instruction set
HasCPUID bool // CPUID identification scheme registers
diff --git a/vendor/golang.org/x/sys/cpu/cpu_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_arm64.go
index af2aa99f9f..f449c679fe 100644
--- a/vendor/golang.org/x/sys/cpu/cpu_arm64.go
+++ b/vendor/golang.org/x/sys/cpu/cpu_arm64.go
@@ -65,10 +65,10 @@ func setMinimalFeatures() {
func readARM64Registers() {
Initialized = true
- parseARM64SystemRegisters(getisar0(), getisar1(), getpfr0())
+ parseARM64SystemRegisters(getisar0(), getisar1(), getmmfr1(), getpfr0())
}
-func parseARM64SystemRegisters(isar0, isar1, pfr0 uint64) {
+func parseARM64SystemRegisters(isar0, isar1, mmfr1, pfr0 uint64) {
// ID_AA64ISAR0_EL1
switch extractBits(isar0, 4, 7) {
case 1:
@@ -152,6 +152,22 @@ func parseARM64SystemRegisters(isar0, isar1, pfr0 uint64) {
ARM64.HasI8MM = true
}
+ // ID_AA64MMFR1_EL1
+ switch extractBits(mmfr1, 12, 15) {
+ case 1, 2:
+ ARM64.HasHPDS = true
+ }
+
+ switch extractBits(mmfr1, 16, 19) {
+ case 1:
+ ARM64.HasLOR = true
+ }
+
+ switch extractBits(mmfr1, 20, 23) {
+ case 1, 2, 3:
+ ARM64.HasPAN = true
+ }
+
// ID_AA64PFR0_EL1
switch extractBits(pfr0, 16, 19) {
case 0:
diff --git a/vendor/golang.org/x/sys/cpu/cpu_arm64.s b/vendor/golang.org/x/sys/cpu/cpu_arm64.s
index 22cc99844a..a4f24b3b0c 100644
--- a/vendor/golang.org/x/sys/cpu/cpu_arm64.s
+++ b/vendor/golang.org/x/sys/cpu/cpu_arm64.s
@@ -9,31 +9,34 @@
// func getisar0() uint64
TEXT ·getisar0(SB),NOSPLIT,$0-8
// get Instruction Set Attributes 0 into x0
- // mrs x0, ID_AA64ISAR0_EL1 = d5380600
- WORD $0xd5380600
+ MRS ID_AA64ISAR0_EL1, R0
MOVD R0, ret+0(FP)
RET
// func getisar1() uint64
TEXT ·getisar1(SB),NOSPLIT,$0-8
// get Instruction Set Attributes 1 into x0
- // mrs x0, ID_AA64ISAR1_EL1 = d5380620
- WORD $0xd5380620
+ MRS ID_AA64ISAR1_EL1, R0
+ MOVD R0, ret+0(FP)
+ RET
+
+// func getmmfr1() uint64
+TEXT ·getmmfr1(SB),NOSPLIT,$0-8
+ // get Memory Model Feature Register 1 into x0
+ MRS ID_AA64MMFR1_EL1, R0
MOVD R0, ret+0(FP)
RET
// func getpfr0() uint64
TEXT ·getpfr0(SB),NOSPLIT,$0-8
// get Processor Feature Register 0 into x0
- // mrs x0, ID_AA64PFR0_EL1 = d5380400
- WORD $0xd5380400
+ MRS ID_AA64PFR0_EL1, R0
MOVD R0, ret+0(FP)
RET
// func getzfr0() uint64
TEXT ·getzfr0(SB),NOSPLIT,$0-8
// get SVE Feature Register 0 into x0
- // mrs x0, ID_AA64ZFR0_EL1 = d5380480
- WORD $0xd5380480
+ MRS ID_AA64ZFR0_EL1, R0
MOVD R0, ret+0(FP)
RET
diff --git a/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go
index 6ac6e1efb2..e3fc5a8d31 100644
--- a/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go
+++ b/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go
@@ -8,5 +8,6 @@ package cpu
func getisar0() uint64
func getisar1() uint64
+func getmmfr1() uint64
func getpfr0() uint64
func getzfr0() uint64
diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_gccgo_arm64.go
index 7f1946780b..8df2079e15 100644
--- a/vendor/golang.org/x/sys/cpu/cpu_gccgo_arm64.go
+++ b/vendor/golang.org/x/sys/cpu/cpu_gccgo_arm64.go
@@ -8,4 +8,5 @@ package cpu
func getisar0() uint64 { return 0 }
func getisar1() uint64 { return 0 }
+func getmmfr1() uint64 { return 0 }
func getpfr0() uint64 { return 0 }
diff --git a/vendor/golang.org/x/sys/cpu/cpu_netbsd_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_netbsd_arm64.go
index ebfb3fc8e7..19aea0633e 100644
--- a/vendor/golang.org/x/sys/cpu/cpu_netbsd_arm64.go
+++ b/vendor/golang.org/x/sys/cpu/cpu_netbsd_arm64.go
@@ -167,7 +167,7 @@ func doinit() {
setMinimalFeatures()
return
}
- parseARM64SystemRegisters(cpuid.aa64isar0, cpuid.aa64isar1, cpuid.aa64pfr0)
+ parseARM64SystemRegisters(cpuid.aa64isar0, cpuid.aa64isar1, cpuid.aa64mmfr1, cpuid.aa64pfr0)
Initialized = true
}
diff --git a/vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.go
index 85b64d5ccb..87fd3a7780 100644
--- a/vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.go
+++ b/vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.go
@@ -59,7 +59,7 @@ func doinit() {
if !ok {
return
}
- parseARM64SystemRegisters(isar0, isar1, 0)
+ parseARM64SystemRegisters(isar0, isar1, 0, 0)
Initialized = true
}
diff --git a/vendor/golang.org/x/sys/unix/affinity_linux.go b/vendor/golang.org/x/sys/unix/affinity_linux.go
index 3c7a6d6e2f..3ea470387b 100644
--- a/vendor/golang.org/x/sys/unix/affinity_linux.go
+++ b/vendor/golang.org/x/sys/unix/affinity_linux.go
@@ -41,6 +41,15 @@ func (s *CPUSet) Zero() {
clear(s[:])
}
+// Fill adds all possible CPU bits to the set s. On Linux, [SchedSetaffinity]
+// will silently ignore any invalid CPU bits in [CPUSet] so this is an
+// efficient way of resetting the CPU affinity of a process.
+func (s *CPUSet) Fill() {
+ for i := range s {
+ s[i] = ^cpuMask(0)
+ }
+}
+
func cpuBitsIndex(cpu int) int {
return cpu / _NCPUBITS
}
diff --git a/vendor/golang.org/x/sys/unix/fdset.go b/vendor/golang.org/x/sys/unix/fdset.go
index 9e83d18cd0..62ed12645f 100644
--- a/vendor/golang.org/x/sys/unix/fdset.go
+++ b/vendor/golang.org/x/sys/unix/fdset.go
@@ -23,7 +23,5 @@ func (fds *FdSet) IsSet(fd int) bool {
// Zero clears the set fds.
func (fds *FdSet) Zero() {
- for i := range fds.Bits {
- fds.Bits[i] = 0
- }
+ clear(fds.Bits[:])
}
diff --git a/vendor/golang.org/x/sys/unix/ifreq_linux.go b/vendor/golang.org/x/sys/unix/ifreq_linux.go
index 848840ae4c..309f5a2b0c 100644
--- a/vendor/golang.org/x/sys/unix/ifreq_linux.go
+++ b/vendor/golang.org/x/sys/unix/ifreq_linux.go
@@ -111,9 +111,7 @@ func (ifr *Ifreq) SetUint32(v uint32) {
// clear zeroes the ifreq's union field to prevent trailing garbage data from
// being sent to the kernel if an ifreq is reused.
func (ifr *Ifreq) clear() {
- for i := range ifr.raw.Ifru {
- ifr.raw.Ifru[i] = 0
- }
+ clear(ifr.raw.Ifru[:])
}
// TODO(mdlayher): export as IfreqData? For now we can provide helpers such as
diff --git a/vendor/golang.org/x/sys/unix/mkall.sh b/vendor/golang.org/x/sys/unix/mkall.sh
index e6f31d374d..d0ed611912 100644
--- a/vendor/golang.org/x/sys/unix/mkall.sh
+++ b/vendor/golang.org/x/sys/unix/mkall.sh
@@ -49,6 +49,7 @@ esac
if [[ "$GOOS" = "linux" ]]; then
# Use the Docker-based build system
# Files generated through docker (use $cmd so you can Ctl-C the build or run)
+ set -e
$cmd docker build --tag generate:$GOOS $GOOS
$cmd docker run --interactive --tty --volume $(cd -- "$(dirname -- "$0")/.." && pwd):/build generate:$GOOS
exit
diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh
index d1c8b2640e..42517077c4 100644
--- a/vendor/golang.org/x/sys/unix/mkerrors.sh
+++ b/vendor/golang.org/x/sys/unix/mkerrors.sh
@@ -226,6 +226,7 @@ struct ltchars {
#include
#include
#include
+#include
#include
#include
#include
@@ -529,6 +530,7 @@ ccflags="$@"
$2 ~ /^O[CNPFPL][A-Z]+[^_][A-Z]+$/ ||
$2 ~ /^(NL|CR|TAB|BS|VT|FF)DLY$/ ||
$2 ~ /^(NL|CR|TAB|BS|VT|FF)[0-9]$/ ||
+ $2 ~ /^(DT|EI|ELF|EV|NN|NT|PF|SHF|SHN|SHT|STB|STT|VER)_/ ||
$2 ~ /^O?XTABS$/ ||
$2 ~ /^TC[IO](ON|OFF)$/ ||
$2 ~ /^IN_/ ||
diff --git a/vendor/golang.org/x/sys/unix/syscall_linux.go b/vendor/golang.org/x/sys/unix/syscall_linux.go
index 4958a65708..06c0eea6fb 100644
--- a/vendor/golang.org/x/sys/unix/syscall_linux.go
+++ b/vendor/golang.org/x/sys/unix/syscall_linux.go
@@ -801,9 +801,7 @@ func (sa *SockaddrPPPoE) sockaddr() (unsafe.Pointer, _Socklen, error) {
// one. The kernel expects SID to be in network byte order.
binary.BigEndian.PutUint16(sa.raw[6:8], sa.SID)
copy(sa.raw[8:14], sa.Remote)
- for i := 14; i < 14+IFNAMSIZ; i++ {
- sa.raw[i] = 0
- }
+ clear(sa.raw[14 : 14+IFNAMSIZ])
copy(sa.raw[14:], sa.Dev)
return unsafe.Pointer(&sa.raw), SizeofSockaddrPPPoX, nil
}
@@ -2645,3 +2643,9 @@ func SchedGetAttr(pid int, flags uint) (*SchedAttr, error) {
//sys Cachestat(fd uint, crange *CachestatRange, cstat *Cachestat_t, flags uint) (err error)
//sys Mseal(b []byte, flags uint) (err error)
+
+//sys setMemPolicy(mode int, mask *CPUSet, size int) (err error) = SYS_SET_MEMPOLICY
+
+func SetMemPolicy(mode int, mask *CPUSet) error {
+ return setMemPolicy(mode, mask, _CPU_SETSIZE)
+}
diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd.go b/vendor/golang.org/x/sys/unix/syscall_netbsd.go
index 88162099af..34a4676973 100644
--- a/vendor/golang.org/x/sys/unix/syscall_netbsd.go
+++ b/vendor/golang.org/x/sys/unix/syscall_netbsd.go
@@ -248,6 +248,23 @@ func Statvfs(path string, buf *Statvfs_t) (err error) {
return Statvfs1(path, buf, ST_WAIT)
}
+func Getvfsstat(buf []Statvfs_t, flags int) (n int, err error) {
+ var (
+ _p0 unsafe.Pointer
+ bufsize uintptr
+ )
+ if len(buf) > 0 {
+ _p0 = unsafe.Pointer(&buf[0])
+ bufsize = unsafe.Sizeof(Statvfs_t{}) * uintptr(len(buf))
+ }
+ r0, _, e1 := Syscall(SYS_GETVFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
+ n = int(r0)
+ if e1 != 0 {
+ err = e1
+ }
+ return
+}
+
/*
* Exposed directly
*/
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux.go b/vendor/golang.org/x/sys/unix/zerrors_linux.go
index b6db27d937..d0a75da572 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux.go
@@ -853,20 +853,86 @@ const (
DM_VERSION_MAJOR = 0x4
DM_VERSION_MINOR = 0x32
DM_VERSION_PATCHLEVEL = 0x0
+ DT_ADDRRNGHI = 0x6ffffeff
+ DT_ADDRRNGLO = 0x6ffffe00
DT_BLK = 0x6
DT_CHR = 0x2
+ DT_DEBUG = 0x15
DT_DIR = 0x4
+ DT_ENCODING = 0x20
DT_FIFO = 0x1
+ DT_FINI = 0xd
+ DT_FLAGS_1 = 0x6ffffffb
+ DT_GNU_HASH = 0x6ffffef5
+ DT_HASH = 0x4
+ DT_HIOS = 0x6ffff000
+ DT_HIPROC = 0x7fffffff
+ DT_INIT = 0xc
+ DT_JMPREL = 0x17
DT_LNK = 0xa
+ DT_LOOS = 0x6000000d
+ DT_LOPROC = 0x70000000
+ DT_NEEDED = 0x1
+ DT_NULL = 0x0
+ DT_PLTGOT = 0x3
+ DT_PLTREL = 0x14
+ DT_PLTRELSZ = 0x2
DT_REG = 0x8
+ DT_REL = 0x11
+ DT_RELA = 0x7
+ DT_RELACOUNT = 0x6ffffff9
+ DT_RELAENT = 0x9
+ DT_RELASZ = 0x8
+ DT_RELCOUNT = 0x6ffffffa
+ DT_RELENT = 0x13
+ DT_RELSZ = 0x12
+ DT_RPATH = 0xf
DT_SOCK = 0xc
+ DT_SONAME = 0xe
+ DT_STRSZ = 0xa
+ DT_STRTAB = 0x5
+ DT_SYMBOLIC = 0x10
+ DT_SYMENT = 0xb
+ DT_SYMTAB = 0x6
+ DT_TEXTREL = 0x16
DT_UNKNOWN = 0x0
+ DT_VALRNGHI = 0x6ffffdff
+ DT_VALRNGLO = 0x6ffffd00
+ DT_VERDEF = 0x6ffffffc
+ DT_VERDEFNUM = 0x6ffffffd
+ DT_VERNEED = 0x6ffffffe
+ DT_VERNEEDNUM = 0x6fffffff
+ DT_VERSYM = 0x6ffffff0
DT_WHT = 0xe
ECHO = 0x8
ECRYPTFS_SUPER_MAGIC = 0xf15f
EFD_SEMAPHORE = 0x1
EFIVARFS_MAGIC = 0xde5e81e4
EFS_SUPER_MAGIC = 0x414a53
+ EI_CLASS = 0x4
+ EI_DATA = 0x5
+ EI_MAG0 = 0x0
+ EI_MAG1 = 0x1
+ EI_MAG2 = 0x2
+ EI_MAG3 = 0x3
+ EI_NIDENT = 0x10
+ EI_OSABI = 0x7
+ EI_PAD = 0x8
+ EI_VERSION = 0x6
+ ELFCLASS32 = 0x1
+ ELFCLASS64 = 0x2
+ ELFCLASSNONE = 0x0
+ ELFCLASSNUM = 0x3
+ ELFDATA2LSB = 0x1
+ ELFDATA2MSB = 0x2
+ ELFDATANONE = 0x0
+ ELFMAG = "\177ELF"
+ ELFMAG0 = 0x7f
+ ELFMAG1 = 'E'
+ ELFMAG2 = 'L'
+ ELFMAG3 = 'F'
+ ELFOSABI_LINUX = 0x3
+ ELFOSABI_NONE = 0x0
EM_386 = 0x3
EM_486 = 0x6
EM_68K = 0x4
@@ -1152,14 +1218,24 @@ const (
ETH_P_WCCP = 0x883e
ETH_P_X25 = 0x805
ETH_P_XDSA = 0xf8
+ ET_CORE = 0x4
+ ET_DYN = 0x3
+ ET_EXEC = 0x2
+ ET_HIPROC = 0xffff
+ ET_LOPROC = 0xff00
+ ET_NONE = 0x0
+ ET_REL = 0x1
EV_ABS = 0x3
EV_CNT = 0x20
+ EV_CURRENT = 0x1
EV_FF = 0x15
EV_FF_STATUS = 0x17
EV_KEY = 0x1
EV_LED = 0x11
EV_MAX = 0x1f
EV_MSC = 0x4
+ EV_NONE = 0x0
+ EV_NUM = 0x2
EV_PWR = 0x16
EV_REL = 0x2
EV_REP = 0x14
@@ -2276,7 +2352,167 @@ const (
NLM_F_REPLACE = 0x100
NLM_F_REQUEST = 0x1
NLM_F_ROOT = 0x100
+ NN_386_IOPERM = "LINUX"
+ NN_386_TLS = "LINUX"
+ NN_ARC_V2 = "LINUX"
+ NN_ARM_FPMR = "LINUX"
+ NN_ARM_GCS = "LINUX"
+ NN_ARM_HW_BREAK = "LINUX"
+ NN_ARM_HW_WATCH = "LINUX"
+ NN_ARM_PACA_KEYS = "LINUX"
+ NN_ARM_PACG_KEYS = "LINUX"
+ NN_ARM_PAC_ENABLED_KEYS = "LINUX"
+ NN_ARM_PAC_MASK = "LINUX"
+ NN_ARM_POE = "LINUX"
+ NN_ARM_SSVE = "LINUX"
+ NN_ARM_SVE = "LINUX"
+ NN_ARM_SYSTEM_CALL = "LINUX"
+ NN_ARM_TAGGED_ADDR_CTRL = "LINUX"
+ NN_ARM_TLS = "LINUX"
+ NN_ARM_VFP = "LINUX"
+ NN_ARM_ZA = "LINUX"
+ NN_ARM_ZT = "LINUX"
+ NN_AUXV = "CORE"
+ NN_FILE = "CORE"
+ NN_GNU_PROPERTY_TYPE_0 = "GNU"
+ NN_LOONGARCH_CPUCFG = "LINUX"
+ NN_LOONGARCH_CSR = "LINUX"
+ NN_LOONGARCH_HW_BREAK = "LINUX"
+ NN_LOONGARCH_HW_WATCH = "LINUX"
+ NN_LOONGARCH_LASX = "LINUX"
+ NN_LOONGARCH_LBT = "LINUX"
+ NN_LOONGARCH_LSX = "LINUX"
+ NN_MIPS_DSP = "LINUX"
+ NN_MIPS_FP_MODE = "LINUX"
+ NN_MIPS_MSA = "LINUX"
+ NN_PPC_DEXCR = "LINUX"
+ NN_PPC_DSCR = "LINUX"
+ NN_PPC_EBB = "LINUX"
+ NN_PPC_HASHKEYR = "LINUX"
+ NN_PPC_PKEY = "LINUX"
+ NN_PPC_PMU = "LINUX"
+ NN_PPC_PPR = "LINUX"
+ NN_PPC_SPE = "LINUX"
+ NN_PPC_TAR = "LINUX"
+ NN_PPC_TM_CDSCR = "LINUX"
+ NN_PPC_TM_CFPR = "LINUX"
+ NN_PPC_TM_CGPR = "LINUX"
+ NN_PPC_TM_CPPR = "LINUX"
+ NN_PPC_TM_CTAR = "LINUX"
+ NN_PPC_TM_CVMX = "LINUX"
+ NN_PPC_TM_CVSX = "LINUX"
+ NN_PPC_TM_SPR = "LINUX"
+ NN_PPC_VMX = "LINUX"
+ NN_PPC_VSX = "LINUX"
+ NN_PRFPREG = "CORE"
+ NN_PRPSINFO = "CORE"
+ NN_PRSTATUS = "CORE"
+ NN_PRXFPREG = "LINUX"
+ NN_RISCV_CSR = "LINUX"
+ NN_RISCV_TAGGED_ADDR_CTRL = "LINUX"
+ NN_RISCV_VECTOR = "LINUX"
+ NN_S390_CTRS = "LINUX"
+ NN_S390_GS_BC = "LINUX"
+ NN_S390_GS_CB = "LINUX"
+ NN_S390_HIGH_GPRS = "LINUX"
+ NN_S390_LAST_BREAK = "LINUX"
+ NN_S390_PREFIX = "LINUX"
+ NN_S390_PV_CPU_DATA = "LINUX"
+ NN_S390_RI_CB = "LINUX"
+ NN_S390_SYSTEM_CALL = "LINUX"
+ NN_S390_TDB = "LINUX"
+ NN_S390_TIMER = "LINUX"
+ NN_S390_TODCMP = "LINUX"
+ NN_S390_TODPREG = "LINUX"
+ NN_S390_VXRS_HIGH = "LINUX"
+ NN_S390_VXRS_LOW = "LINUX"
+ NN_SIGINFO = "CORE"
+ NN_TASKSTRUCT = "CORE"
+ NN_VMCOREDD = "LINUX"
+ NN_X86_SHSTK = "LINUX"
+ NN_X86_XSAVE_LAYOUT = "LINUX"
+ NN_X86_XSTATE = "LINUX"
NSFS_MAGIC = 0x6e736673
+ NT_386_IOPERM = 0x201
+ NT_386_TLS = 0x200
+ NT_ARC_V2 = 0x600
+ NT_ARM_FPMR = 0x40e
+ NT_ARM_GCS = 0x410
+ NT_ARM_HW_BREAK = 0x402
+ NT_ARM_HW_WATCH = 0x403
+ NT_ARM_PACA_KEYS = 0x407
+ NT_ARM_PACG_KEYS = 0x408
+ NT_ARM_PAC_ENABLED_KEYS = 0x40a
+ NT_ARM_PAC_MASK = 0x406
+ NT_ARM_POE = 0x40f
+ NT_ARM_SSVE = 0x40b
+ NT_ARM_SVE = 0x405
+ NT_ARM_SYSTEM_CALL = 0x404
+ NT_ARM_TAGGED_ADDR_CTRL = 0x409
+ NT_ARM_TLS = 0x401
+ NT_ARM_VFP = 0x400
+ NT_ARM_ZA = 0x40c
+ NT_ARM_ZT = 0x40d
+ NT_AUXV = 0x6
+ NT_FILE = 0x46494c45
+ NT_GNU_PROPERTY_TYPE_0 = 0x5
+ NT_LOONGARCH_CPUCFG = 0xa00
+ NT_LOONGARCH_CSR = 0xa01
+ NT_LOONGARCH_HW_BREAK = 0xa05
+ NT_LOONGARCH_HW_WATCH = 0xa06
+ NT_LOONGARCH_LASX = 0xa03
+ NT_LOONGARCH_LBT = 0xa04
+ NT_LOONGARCH_LSX = 0xa02
+ NT_MIPS_DSP = 0x800
+ NT_MIPS_FP_MODE = 0x801
+ NT_MIPS_MSA = 0x802
+ NT_PPC_DEXCR = 0x111
+ NT_PPC_DSCR = 0x105
+ NT_PPC_EBB = 0x106
+ NT_PPC_HASHKEYR = 0x112
+ NT_PPC_PKEY = 0x110
+ NT_PPC_PMU = 0x107
+ NT_PPC_PPR = 0x104
+ NT_PPC_SPE = 0x101
+ NT_PPC_TAR = 0x103
+ NT_PPC_TM_CDSCR = 0x10f
+ NT_PPC_TM_CFPR = 0x109
+ NT_PPC_TM_CGPR = 0x108
+ NT_PPC_TM_CPPR = 0x10e
+ NT_PPC_TM_CTAR = 0x10d
+ NT_PPC_TM_CVMX = 0x10a
+ NT_PPC_TM_CVSX = 0x10b
+ NT_PPC_TM_SPR = 0x10c
+ NT_PPC_VMX = 0x100
+ NT_PPC_VSX = 0x102
+ NT_PRFPREG = 0x2
+ NT_PRPSINFO = 0x3
+ NT_PRSTATUS = 0x1
+ NT_PRXFPREG = 0x46e62b7f
+ NT_RISCV_CSR = 0x900
+ NT_RISCV_TAGGED_ADDR_CTRL = 0x902
+ NT_RISCV_VECTOR = 0x901
+ NT_S390_CTRS = 0x304
+ NT_S390_GS_BC = 0x30c
+ NT_S390_GS_CB = 0x30b
+ NT_S390_HIGH_GPRS = 0x300
+ NT_S390_LAST_BREAK = 0x306
+ NT_S390_PREFIX = 0x305
+ NT_S390_PV_CPU_DATA = 0x30e
+ NT_S390_RI_CB = 0x30d
+ NT_S390_SYSTEM_CALL = 0x307
+ NT_S390_TDB = 0x308
+ NT_S390_TIMER = 0x301
+ NT_S390_TODCMP = 0x302
+ NT_S390_TODPREG = 0x303
+ NT_S390_VXRS_HIGH = 0x30a
+ NT_S390_VXRS_LOW = 0x309
+ NT_SIGINFO = 0x53494749
+ NT_TASKSTRUCT = 0x4
+ NT_VMCOREDD = 0x700
+ NT_X86_SHSTK = 0x204
+ NT_X86_XSAVE_LAYOUT = 0x205
+ NT_X86_XSTATE = 0x202
OCFS2_SUPER_MAGIC = 0x7461636f
OCRNL = 0x8
OFDEL = 0x80
@@ -2463,6 +2699,59 @@ const (
PERF_RECORD_MISC_USER = 0x2
PERF_SAMPLE_BRANCH_PLM_ALL = 0x7
PERF_SAMPLE_WEIGHT_TYPE = 0x1004000
+ PF_ALG = 0x26
+ PF_APPLETALK = 0x5
+ PF_ASH = 0x12
+ PF_ATMPVC = 0x8
+ PF_ATMSVC = 0x14
+ PF_AX25 = 0x3
+ PF_BLUETOOTH = 0x1f
+ PF_BRIDGE = 0x7
+ PF_CAIF = 0x25
+ PF_CAN = 0x1d
+ PF_DECnet = 0xc
+ PF_ECONET = 0x13
+ PF_FILE = 0x1
+ PF_IB = 0x1b
+ PF_IEEE802154 = 0x24
+ PF_INET = 0x2
+ PF_INET6 = 0xa
+ PF_IPX = 0x4
+ PF_IRDA = 0x17
+ PF_ISDN = 0x22
+ PF_IUCV = 0x20
+ PF_KCM = 0x29
+ PF_KEY = 0xf
+ PF_LLC = 0x1a
+ PF_LOCAL = 0x1
+ PF_MAX = 0x2e
+ PF_MCTP = 0x2d
+ PF_MPLS = 0x1c
+ PF_NETBEUI = 0xd
+ PF_NETLINK = 0x10
+ PF_NETROM = 0x6
+ PF_NFC = 0x27
+ PF_PACKET = 0x11
+ PF_PHONET = 0x23
+ PF_PPPOX = 0x18
+ PF_QIPCRTR = 0x2a
+ PF_R = 0x4
+ PF_RDS = 0x15
+ PF_ROSE = 0xb
+ PF_ROUTE = 0x10
+ PF_RXRPC = 0x21
+ PF_SECURITY = 0xe
+ PF_SMC = 0x2b
+ PF_SNA = 0x16
+ PF_TIPC = 0x1e
+ PF_UNIX = 0x1
+ PF_UNSPEC = 0x0
+ PF_VSOCK = 0x28
+ PF_W = 0x2
+ PF_WANPIPE = 0x19
+ PF_X = 0x1
+ PF_X25 = 0x9
+ PF_XDP = 0x2c
PID_FS_MAGIC = 0x50494446
PIPEFS_MAGIC = 0x50495045
PPPIOCGNPMODE = 0xc008744c
@@ -2758,6 +3047,23 @@ const (
PTRACE_SYSCALL_INFO_NONE = 0x0
PTRACE_SYSCALL_INFO_SECCOMP = 0x3
PTRACE_TRACEME = 0x0
+ PT_AARCH64_MEMTAG_MTE = 0x70000002
+ PT_DYNAMIC = 0x2
+ PT_GNU_EH_FRAME = 0x6474e550
+ PT_GNU_PROPERTY = 0x6474e553
+ PT_GNU_RELRO = 0x6474e552
+ PT_GNU_STACK = 0x6474e551
+ PT_HIOS = 0x6fffffff
+ PT_HIPROC = 0x7fffffff
+ PT_INTERP = 0x3
+ PT_LOAD = 0x1
+ PT_LOOS = 0x60000000
+ PT_LOPROC = 0x70000000
+ PT_NOTE = 0x4
+ PT_NULL = 0x0
+ PT_PHDR = 0x6
+ PT_SHLIB = 0x5
+ PT_TLS = 0x7
P_ALL = 0x0
P_PGID = 0x2
P_PID = 0x1
@@ -3091,6 +3397,47 @@ const (
SEEK_MAX = 0x4
SEEK_SET = 0x0
SELINUX_MAGIC = 0xf97cff8c
+ SHF_ALLOC = 0x2
+ SHF_EXCLUDE = 0x8000000
+ SHF_EXECINSTR = 0x4
+ SHF_GROUP = 0x200
+ SHF_INFO_LINK = 0x40
+ SHF_LINK_ORDER = 0x80
+ SHF_MASKOS = 0xff00000
+ SHF_MASKPROC = 0xf0000000
+ SHF_MERGE = 0x10
+ SHF_ORDERED = 0x4000000
+ SHF_OS_NONCONFORMING = 0x100
+ SHF_RELA_LIVEPATCH = 0x100000
+ SHF_RO_AFTER_INIT = 0x200000
+ SHF_STRINGS = 0x20
+ SHF_TLS = 0x400
+ SHF_WRITE = 0x1
+ SHN_ABS = 0xfff1
+ SHN_COMMON = 0xfff2
+ SHN_HIPROC = 0xff1f
+ SHN_HIRESERVE = 0xffff
+ SHN_LIVEPATCH = 0xff20
+ SHN_LOPROC = 0xff00
+ SHN_LORESERVE = 0xff00
+ SHN_UNDEF = 0x0
+ SHT_DYNAMIC = 0x6
+ SHT_DYNSYM = 0xb
+ SHT_HASH = 0x5
+ SHT_HIPROC = 0x7fffffff
+ SHT_HIUSER = 0xffffffff
+ SHT_LOPROC = 0x70000000
+ SHT_LOUSER = 0x80000000
+ SHT_NOBITS = 0x8
+ SHT_NOTE = 0x7
+ SHT_NULL = 0x0
+ SHT_NUM = 0xc
+ SHT_PROGBITS = 0x1
+ SHT_REL = 0x9
+ SHT_RELA = 0x4
+ SHT_SHLIB = 0xa
+ SHT_STRTAB = 0x3
+ SHT_SYMTAB = 0x2
SHUT_RD = 0x0
SHUT_RDWR = 0x2
SHUT_WR = 0x1
@@ -3317,6 +3664,16 @@ const (
STATX_UID = 0x8
STATX_WRITE_ATOMIC = 0x10000
STATX__RESERVED = 0x80000000
+ STB_GLOBAL = 0x1
+ STB_LOCAL = 0x0
+ STB_WEAK = 0x2
+ STT_COMMON = 0x5
+ STT_FILE = 0x4
+ STT_FUNC = 0x2
+ STT_NOTYPE = 0x0
+ STT_OBJECT = 0x1
+ STT_SECTION = 0x3
+ STT_TLS = 0x6
SYNC_FILE_RANGE_WAIT_AFTER = 0x4
SYNC_FILE_RANGE_WAIT_BEFORE = 0x1
SYNC_FILE_RANGE_WRITE = 0x2
@@ -3553,6 +3910,8 @@ const (
UTIME_OMIT = 0x3ffffffe
V9FS_MAGIC = 0x1021997
VERASE = 0x2
+ VER_FLG_BASE = 0x1
+ VER_FLG_WEAK = 0x2
VINTR = 0x0
VKILL = 0x3
VLNEXT = 0xf
diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux.go b/vendor/golang.org/x/sys/unix/zsyscall_linux.go
index 5cc1e8eb2f..8935d10a31 100644
--- a/vendor/golang.org/x/sys/unix/zsyscall_linux.go
+++ b/vendor/golang.org/x/sys/unix/zsyscall_linux.go
@@ -2238,3 +2238,13 @@ func Mseal(b []byte, flags uint) (err error) {
}
return
}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setMemPolicy(mode int, mask *CPUSet, size int) (err error) {
+ _, _, e1 := Syscall(SYS_SET_MEMPOLICY, uintptr(mode), uintptr(unsafe.Pointer(mask)), uintptr(size))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux.go b/vendor/golang.org/x/sys/unix/ztypes_linux.go
index 944e75a11c..c1a4670171 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_linux.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_linux.go
@@ -3590,6 +3590,8 @@ type Nhmsg struct {
Flags uint32
}
+const SizeofNhmsg = 0x8
+
type NexthopGrp struct {
Id uint32
Weight uint8
@@ -3597,6 +3599,8 @@ type NexthopGrp struct {
Resvd2 uint16
}
+const SizeofNexthopGrp = 0x8
+
const (
NHA_UNSPEC = 0x0
NHA_ID = 0x1
@@ -6332,3 +6336,30 @@ type SockDiagReq struct {
}
const RTM_NEWNVLAN = 0x70
+
+const (
+ MPOL_BIND = 0x2
+ MPOL_DEFAULT = 0x0
+ MPOL_F_ADDR = 0x2
+ MPOL_F_MEMS_ALLOWED = 0x4
+ MPOL_F_MOF = 0x8
+ MPOL_F_MORON = 0x10
+ MPOL_F_NODE = 0x1
+ MPOL_F_NUMA_BALANCING = 0x2000
+ MPOL_F_RELATIVE_NODES = 0x4000
+ MPOL_F_SHARED = 0x1
+ MPOL_F_STATIC_NODES = 0x8000
+ MPOL_INTERLEAVE = 0x3
+ MPOL_LOCAL = 0x4
+ MPOL_MAX = 0x7
+ MPOL_MF_INTERNAL = 0x10
+ MPOL_MF_LAZY = 0x8
+ MPOL_MF_MOVE_ALL = 0x4
+ MPOL_MF_MOVE = 0x2
+ MPOL_MF_STRICT = 0x1
+ MPOL_MF_VALID = 0x7
+ MPOL_MODE_FLAGS = 0xe000
+ MPOL_PREFERRED = 0x1
+ MPOL_PREFERRED_MANY = 0x5
+ MPOL_WEIGHTED_INTERLEAVE = 0x6
+)
diff --git a/vendor/golang.org/x/sys/windows/syscall_windows.go b/vendor/golang.org/x/sys/windows/syscall_windows.go
index 640f6b153f..69439df2a4 100644
--- a/vendor/golang.org/x/sys/windows/syscall_windows.go
+++ b/vendor/golang.org/x/sys/windows/syscall_windows.go
@@ -321,6 +321,8 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys SetConsoleOutputCP(cp uint32) (err error) = kernel32.SetConsoleOutputCP
//sys WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) = kernel32.WriteConsoleW
//sys ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) = kernel32.ReadConsoleW
+//sys GetNumberOfConsoleInputEvents(console Handle, numevents *uint32) (err error) = kernel32.GetNumberOfConsoleInputEvents
+//sys FlushConsoleInputBuffer(console Handle) (err error) = kernel32.FlushConsoleInputBuffer
//sys resizePseudoConsole(pconsole Handle, size uint32) (hr error) = kernel32.ResizePseudoConsole
//sys CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) [failretval==InvalidHandle] = kernel32.CreateToolhelp32Snapshot
//sys Module32First(snapshot Handle, moduleEntry *ModuleEntry32) (err error) = kernel32.Module32FirstW
@@ -890,8 +892,12 @@ const socket_error = uintptr(^uint32(0))
//sys MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar
//sys getBestInterfaceEx(sockaddr unsafe.Pointer, pdwBestIfIndex *uint32) (errcode error) = iphlpapi.GetBestInterfaceEx
//sys GetIfEntry2Ex(level uint32, row *MibIfRow2) (errcode error) = iphlpapi.GetIfEntry2Ex
+//sys GetIpForwardEntry2(row *MibIpForwardRow2) (errcode error) = iphlpapi.GetIpForwardEntry2
+//sys GetIpForwardTable2(family uint16, table **MibIpForwardTable2) (errcode error) = iphlpapi.GetIpForwardTable2
//sys GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) = iphlpapi.GetUnicastIpAddressEntry
+//sys FreeMibTable(memory unsafe.Pointer) = iphlpapi.FreeMibTable
//sys NotifyIpInterfaceChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyIpInterfaceChange
+//sys NotifyRouteChange2(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyRouteChange2
//sys NotifyUnicastIpAddressChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyUnicastIpAddressChange
//sys CancelMibChangeNotify2(notificationHandle Handle) (errcode error) = iphlpapi.CancelMibChangeNotify2
@@ -914,6 +920,17 @@ type RawSockaddrInet6 struct {
Scope_id uint32
}
+// RawSockaddrInet is a union that contains an IPv4, an IPv6 address, or an address family. See
+// https://learn.microsoft.com/en-us/windows/win32/api/ws2ipdef/ns-ws2ipdef-sockaddr_inet.
+//
+// A [*RawSockaddrInet] may be converted to a [*RawSockaddrInet4] or [*RawSockaddrInet6] using
+// unsafe, depending on the address family.
+type RawSockaddrInet struct {
+ Family uint16
+ Port uint16
+ Data [6]uint32
+}
+
type RawSockaddr struct {
Family uint16
Data [14]int8
diff --git a/vendor/golang.org/x/sys/windows/types_windows.go b/vendor/golang.org/x/sys/windows/types_windows.go
index 993a2297db..6e4f50eb48 100644
--- a/vendor/golang.org/x/sys/windows/types_windows.go
+++ b/vendor/golang.org/x/sys/windows/types_windows.go
@@ -65,6 +65,22 @@ var signals = [...]string{
15: "terminated",
}
+// File flags for [os.OpenFile]. The O_ prefix is used to indicate
+// that these flags are specific to the OpenFile function.
+const (
+ O_FILE_FLAG_OPEN_NO_RECALL = FILE_FLAG_OPEN_NO_RECALL
+ O_FILE_FLAG_OPEN_REPARSE_POINT = FILE_FLAG_OPEN_REPARSE_POINT
+ O_FILE_FLAG_SESSION_AWARE = FILE_FLAG_SESSION_AWARE
+ O_FILE_FLAG_POSIX_SEMANTICS = FILE_FLAG_POSIX_SEMANTICS
+ O_FILE_FLAG_BACKUP_SEMANTICS = FILE_FLAG_BACKUP_SEMANTICS
+ O_FILE_FLAG_DELETE_ON_CLOSE = FILE_FLAG_DELETE_ON_CLOSE
+ O_FILE_FLAG_SEQUENTIAL_SCAN = FILE_FLAG_SEQUENTIAL_SCAN
+ O_FILE_FLAG_RANDOM_ACCESS = FILE_FLAG_RANDOM_ACCESS
+ O_FILE_FLAG_NO_BUFFERING = FILE_FLAG_NO_BUFFERING
+ O_FILE_FLAG_OVERLAPPED = FILE_FLAG_OVERLAPPED
+ O_FILE_FLAG_WRITE_THROUGH = FILE_FLAG_WRITE_THROUGH
+)
+
const (
FILE_READ_DATA = 0x00000001
FILE_READ_ATTRIBUTES = 0x00000080
@@ -2304,6 +2320,82 @@ type MibIfRow2 struct {
OutQLen uint64
}
+// IP_ADDRESS_PREFIX stores an IP address prefix. See
+// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-ip_address_prefix.
+type IpAddressPrefix struct {
+ Prefix RawSockaddrInet
+ PrefixLength uint8
+}
+
+// NL_ROUTE_ORIGIN enumeration from nldef.h or
+// https://learn.microsoft.com/en-us/windows/win32/api/nldef/ne-nldef-nl_route_origin.
+const (
+ NlroManual = 0
+ NlroWellKnown = 1
+ NlroDHCP = 2
+ NlroRouterAdvertisement = 3
+ Nlro6to4 = 4
+)
+
+// NL_ROUTE_ORIGIN enumeration from nldef.h or
+// https://learn.microsoft.com/en-us/windows/win32/api/nldef/ne-nldef-nl_route_protocol.
+const (
+ MIB_IPPROTO_OTHER = 1
+ MIB_IPPROTO_LOCAL = 2
+ MIB_IPPROTO_NETMGMT = 3
+ MIB_IPPROTO_ICMP = 4
+ MIB_IPPROTO_EGP = 5
+ MIB_IPPROTO_GGP = 6
+ MIB_IPPROTO_HELLO = 7
+ MIB_IPPROTO_RIP = 8
+ MIB_IPPROTO_IS_IS = 9
+ MIB_IPPROTO_ES_IS = 10
+ MIB_IPPROTO_CISCO = 11
+ MIB_IPPROTO_BBN = 12
+ MIB_IPPROTO_OSPF = 13
+ MIB_IPPROTO_BGP = 14
+ MIB_IPPROTO_IDPR = 15
+ MIB_IPPROTO_EIGRP = 16
+ MIB_IPPROTO_DVMRP = 17
+ MIB_IPPROTO_RPL = 18
+ MIB_IPPROTO_DHCP = 19
+ MIB_IPPROTO_NT_AUTOSTATIC = 10002
+ MIB_IPPROTO_NT_STATIC = 10006
+ MIB_IPPROTO_NT_STATIC_NON_DOD = 10007
+)
+
+// MIB_IPFORWARD_ROW2 stores information about an IP route entry. See
+// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_ipforward_row2.
+type MibIpForwardRow2 struct {
+ InterfaceLuid uint64
+ InterfaceIndex uint32
+ DestinationPrefix IpAddressPrefix
+ NextHop RawSockaddrInet
+ SitePrefixLength uint8
+ ValidLifetime uint32
+ PreferredLifetime uint32
+ Metric uint32
+ Protocol uint32
+ Loopback uint8
+ AutoconfigureAddress uint8
+ Publish uint8
+ Immortal uint8
+ Age uint32
+ Origin uint32
+}
+
+// MIB_IPFORWARD_TABLE2 contains a table of IP route entries. See
+// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_ipforward_table2.
+type MibIpForwardTable2 struct {
+ NumEntries uint32
+ Table [1]MibIpForwardRow2
+}
+
+// Rows returns the IP route entries in the table.
+func (t *MibIpForwardTable2) Rows() []MibIpForwardRow2 {
+ return unsafe.Slice(&t.Table[0], t.NumEntries)
+}
+
// MIB_UNICASTIPADDRESS_ROW stores information about a unicast IP address. See
// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_unicastipaddress_row.
type MibUnicastIpAddressRow struct {
diff --git a/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/vendor/golang.org/x/sys/windows/zsyscall_windows.go
index 641a5f4b77..f25b7308a1 100644
--- a/vendor/golang.org/x/sys/windows/zsyscall_windows.go
+++ b/vendor/golang.org/x/sys/windows/zsyscall_windows.go
@@ -182,13 +182,17 @@ var (
procDwmGetWindowAttribute = moddwmapi.NewProc("DwmGetWindowAttribute")
procDwmSetWindowAttribute = moddwmapi.NewProc("DwmSetWindowAttribute")
procCancelMibChangeNotify2 = modiphlpapi.NewProc("CancelMibChangeNotify2")
+ procFreeMibTable = modiphlpapi.NewProc("FreeMibTable")
procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses")
procGetAdaptersInfo = modiphlpapi.NewProc("GetAdaptersInfo")
procGetBestInterfaceEx = modiphlpapi.NewProc("GetBestInterfaceEx")
procGetIfEntry = modiphlpapi.NewProc("GetIfEntry")
procGetIfEntry2Ex = modiphlpapi.NewProc("GetIfEntry2Ex")
+ procGetIpForwardEntry2 = modiphlpapi.NewProc("GetIpForwardEntry2")
+ procGetIpForwardTable2 = modiphlpapi.NewProc("GetIpForwardTable2")
procGetUnicastIpAddressEntry = modiphlpapi.NewProc("GetUnicastIpAddressEntry")
procNotifyIpInterfaceChange = modiphlpapi.NewProc("NotifyIpInterfaceChange")
+ procNotifyRouteChange2 = modiphlpapi.NewProc("NotifyRouteChange2")
procNotifyUnicastIpAddressChange = modiphlpapi.NewProc("NotifyUnicastIpAddressChange")
procAddDllDirectory = modkernel32.NewProc("AddDllDirectory")
procAssignProcessToJobObject = modkernel32.NewProc("AssignProcessToJobObject")
@@ -238,6 +242,7 @@ var (
procFindResourceW = modkernel32.NewProc("FindResourceW")
procFindVolumeClose = modkernel32.NewProc("FindVolumeClose")
procFindVolumeMountPointClose = modkernel32.NewProc("FindVolumeMountPointClose")
+ procFlushConsoleInputBuffer = modkernel32.NewProc("FlushConsoleInputBuffer")
procFlushFileBuffers = modkernel32.NewProc("FlushFileBuffers")
procFlushViewOfFile = modkernel32.NewProc("FlushViewOfFile")
procFormatMessageW = modkernel32.NewProc("FormatMessageW")
@@ -284,6 +289,7 @@ var (
procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW")
procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo")
procGetNamedPipeServerProcessId = modkernel32.NewProc("GetNamedPipeServerProcessId")
+ procGetNumberOfConsoleInputEvents = modkernel32.NewProc("GetNumberOfConsoleInputEvents")
procGetOverlappedResult = modkernel32.NewProc("GetOverlappedResult")
procGetPriorityClass = modkernel32.NewProc("GetPriorityClass")
procGetProcAddress = modkernel32.NewProc("GetProcAddress")
@@ -1622,6 +1628,11 @@ func CancelMibChangeNotify2(notificationHandle Handle) (errcode error) {
return
}
+func FreeMibTable(memory unsafe.Pointer) {
+ syscall.SyscallN(procFreeMibTable.Addr(), uintptr(memory))
+ return
+}
+
func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) {
r0, _, _ := syscall.SyscallN(procGetAdaptersAddresses.Addr(), uintptr(family), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(adapterAddresses)), uintptr(unsafe.Pointer(sizePointer)))
if r0 != 0 {
@@ -1662,6 +1673,22 @@ func GetIfEntry2Ex(level uint32, row *MibIfRow2) (errcode error) {
return
}
+func GetIpForwardEntry2(row *MibIpForwardRow2) (errcode error) {
+ r0, _, _ := syscall.SyscallN(procGetIpForwardEntry2.Addr(), uintptr(unsafe.Pointer(row)))
+ if r0 != 0 {
+ errcode = syscall.Errno(r0)
+ }
+ return
+}
+
+func GetIpForwardTable2(family uint16, table **MibIpForwardTable2) (errcode error) {
+ r0, _, _ := syscall.SyscallN(procGetIpForwardTable2.Addr(), uintptr(family), uintptr(unsafe.Pointer(table)))
+ if r0 != 0 {
+ errcode = syscall.Errno(r0)
+ }
+ return
+}
+
func GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) {
r0, _, _ := syscall.SyscallN(procGetUnicastIpAddressEntry.Addr(), uintptr(unsafe.Pointer(row)))
if r0 != 0 {
@@ -1682,6 +1709,18 @@ func NotifyIpInterfaceChange(family uint16, callback uintptr, callerContext unsa
return
}
+func NotifyRouteChange2(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) {
+ var _p0 uint32
+ if initialNotification {
+ _p0 = 1
+ }
+ r0, _, _ := syscall.SyscallN(procNotifyRouteChange2.Addr(), uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle)))
+ if r0 != 0 {
+ errcode = syscall.Errno(r0)
+ }
+ return
+}
+
func NotifyUnicastIpAddressChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) {
var _p0 uint32
if initialNotification {
@@ -2111,6 +2150,14 @@ func FindVolumeMountPointClose(findVolumeMountPoint Handle) (err error) {
return
}
+func FlushConsoleInputBuffer(console Handle) (err error) {
+ r1, _, e1 := syscall.SyscallN(procFlushConsoleInputBuffer.Addr(), uintptr(console))
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
func FlushFileBuffers(handle Handle) (err error) {
r1, _, e1 := syscall.SyscallN(procFlushFileBuffers.Addr(), uintptr(handle))
if r1 == 0 {
@@ -2481,6 +2528,14 @@ func GetNamedPipeServerProcessId(pipe Handle, serverProcessID *uint32) (err erro
return
}
+func GetNumberOfConsoleInputEvents(console Handle, numevents *uint32) (err error) {
+ r1, _, e1 := syscall.SyscallN(procGetNumberOfConsoleInputEvents.Addr(), uintptr(console), uintptr(unsafe.Pointer(numevents)))
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
func GetOverlappedResult(handle Handle, overlapped *Overlapped, done *uint32, wait bool) (err error) {
var _p0 uint32
if wait {
diff --git a/vendor/golang.org/x/term/terminal.go b/vendor/golang.org/x/term/terminal.go
index bddb2e2aeb..9255449b9b 100644
--- a/vendor/golang.org/x/term/terminal.go
+++ b/vendor/golang.org/x/term/terminal.go
@@ -413,7 +413,7 @@ func (t *Terminal) eraseNPreviousChars(n int) {
}
}
-// countToLeftWord returns then number of characters from the cursor to the
+// countToLeftWord returns the number of characters from the cursor to the
// start of the previous word.
func (t *Terminal) countToLeftWord() int {
if t.pos == 0 {
@@ -438,7 +438,7 @@ func (t *Terminal) countToLeftWord() int {
return t.pos - pos
}
-// countToRightWord returns then number of characters from the cursor to the
+// countToRightWord returns the number of characters from the cursor to the
// start of the next word.
func (t *Terminal) countToRightWord() int {
pos := t.pos
@@ -478,7 +478,7 @@ func visualLength(runes []rune) int {
return length
}
-// histroryAt unlocks the terminal and relocks it while calling History.At.
+// historyAt unlocks the terminal and relocks it while calling History.At.
func (t *Terminal) historyAt(idx int) (string, bool) {
t.lock.Unlock() // Unlock to avoid deadlock if History methods use the output writer.
defer t.lock.Lock() // panic in At (or Len) protection.
diff --git a/vendor/golang.org/x/text/unicode/bidi/core.go b/vendor/golang.org/x/text/unicode/bidi/core.go
index 9d2ae547b5..fb8273236d 100644
--- a/vendor/golang.org/x/text/unicode/bidi/core.go
+++ b/vendor/golang.org/x/text/unicode/bidi/core.go
@@ -427,13 +427,6 @@ type isolatingRunSequence struct {
func (i *isolatingRunSequence) Len() int { return len(i.indexes) }
-func maxLevel(a, b level) level {
- if a > b {
- return a
- }
- return b
-}
-
// Rule X10, second bullet: Determine the start-of-sequence (sos) and end-of-sequence (eos) types,
// either L or R, for each isolating run sequence.
func (p *paragraph) isolatingRunSequence(indexes []int) *isolatingRunSequence {
@@ -474,8 +467,8 @@ func (p *paragraph) isolatingRunSequence(indexes []int) *isolatingRunSequence {
indexes: indexes,
types: types,
level: level,
- sos: typeForLevel(maxLevel(prevLevel, level)),
- eos: typeForLevel(maxLevel(succLevel, level)),
+ sos: typeForLevel(max(prevLevel, level)),
+ eos: typeForLevel(max(succLevel, level)),
}
}
diff --git a/vendor/golang.org/x/tools/go/ast/astutil/imports.go b/vendor/golang.org/x/tools/go/ast/astutil/imports.go
index 5e5601aa46..5bacc0fa49 100644
--- a/vendor/golang.org/x/tools/go/ast/astutil/imports.go
+++ b/vendor/golang.org/x/tools/go/ast/astutil/imports.go
@@ -209,48 +209,46 @@ func DeleteImport(fset *token.FileSet, f *ast.File, path string) (deleted bool)
// DeleteNamedImport deletes the import with the given name and path from the file f, if present.
// If there are duplicate import declarations, all matching ones are deleted.
func DeleteNamedImport(fset *token.FileSet, f *ast.File, name, path string) (deleted bool) {
- var delspecs []*ast.ImportSpec
- var delcomments []*ast.CommentGroup
+ var (
+ delspecs = make(map[*ast.ImportSpec]bool)
+ delcomments = make(map[*ast.CommentGroup]bool)
+ )
// Find the import nodes that import path, if any.
for i := 0; i < len(f.Decls); i++ {
- decl := f.Decls[i]
- gen, ok := decl.(*ast.GenDecl)
+ gen, ok := f.Decls[i].(*ast.GenDecl)
if !ok || gen.Tok != token.IMPORT {
continue
}
for j := 0; j < len(gen.Specs); j++ {
- spec := gen.Specs[j]
- impspec := spec.(*ast.ImportSpec)
+ impspec := gen.Specs[j].(*ast.ImportSpec)
if importName(impspec) != name || importPath(impspec) != path {
continue
}
// We found an import spec that imports path.
// Delete it.
- delspecs = append(delspecs, impspec)
+ delspecs[impspec] = true
deleted = true
- copy(gen.Specs[j:], gen.Specs[j+1:])
- gen.Specs = gen.Specs[:len(gen.Specs)-1]
+ gen.Specs = slices.Delete(gen.Specs, j, j+1)
// If this was the last import spec in this decl,
// delete the decl, too.
if len(gen.Specs) == 0 {
- copy(f.Decls[i:], f.Decls[i+1:])
- f.Decls = f.Decls[:len(f.Decls)-1]
+ f.Decls = slices.Delete(f.Decls, i, i+1)
i--
break
} else if len(gen.Specs) == 1 {
if impspec.Doc != nil {
- delcomments = append(delcomments, impspec.Doc)
+ delcomments[impspec.Doc] = true
}
if impspec.Comment != nil {
- delcomments = append(delcomments, impspec.Comment)
+ delcomments[impspec.Comment] = true
}
for _, cg := range f.Comments {
// Found comment on the same line as the import spec.
if cg.End() < impspec.Pos() && fset.Position(cg.End()).Line == fset.Position(impspec.Pos()).Line {
- delcomments = append(delcomments, cg)
+ delcomments[cg] = true
break
}
}
@@ -294,38 +292,21 @@ func DeleteNamedImport(fset *token.FileSet, f *ast.File, name, path string) (del
}
// Delete imports from f.Imports.
- for i := 0; i < len(f.Imports); i++ {
- imp := f.Imports[i]
- for j, del := range delspecs {
- if imp == del {
- copy(f.Imports[i:], f.Imports[i+1:])
- f.Imports = f.Imports[:len(f.Imports)-1]
- copy(delspecs[j:], delspecs[j+1:])
- delspecs = delspecs[:len(delspecs)-1]
- i--
- break
- }
- }
+ before := len(f.Imports)
+ f.Imports = slices.DeleteFunc(f.Imports, func(imp *ast.ImportSpec) bool {
+ _, ok := delspecs[imp]
+ return ok
+ })
+ if len(f.Imports)+len(delspecs) != before {
+ // This can happen when the AST is invalid (i.e. imports differ between f.Decls and f.Imports).
+ panic(fmt.Sprintf("deleted specs from Decls but not Imports: %v", delspecs))
}
// Delete comments from f.Comments.
- for i := 0; i < len(f.Comments); i++ {
- cg := f.Comments[i]
- for j, del := range delcomments {
- if cg == del {
- copy(f.Comments[i:], f.Comments[i+1:])
- f.Comments = f.Comments[:len(f.Comments)-1]
- copy(delcomments[j:], delcomments[j+1:])
- delcomments = delcomments[:len(delcomments)-1]
- i--
- break
- }
- }
- }
-
- if len(delspecs) > 0 {
- panic(fmt.Sprintf("deleted specs from Decls but not Imports: %v", delspecs))
- }
+ f.Comments = slices.DeleteFunc(f.Comments, func(cg *ast.CommentGroup) bool {
+ _, ok := delcomments[cg]
+ return ok
+ })
return
}
diff --git a/vendor/golang.org/x/tools/go/ast/edge/edge.go b/vendor/golang.org/x/tools/go/ast/edge/edge.go
new file mode 100644
index 0000000000..4f6ccfd6e5
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/ast/edge/edge.go
@@ -0,0 +1,295 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package edge defines identifiers for each field of an ast.Node
+// struct type that refers to another Node.
+package edge
+
+import (
+ "fmt"
+ "go/ast"
+ "reflect"
+)
+
+// A Kind describes a field of an ast.Node struct.
+type Kind uint8
+
+// String returns a description of the edge kind.
+func (k Kind) String() string {
+ if k == Invalid {
+ return ""
+ }
+ info := fieldInfos[k]
+ return fmt.Sprintf("%v.%s", info.nodeType.Elem().Name(), info.name)
+}
+
+// NodeType returns the pointer-to-struct type of the ast.Node implementation.
+func (k Kind) NodeType() reflect.Type { return fieldInfos[k].nodeType }
+
+// FieldName returns the name of the field.
+func (k Kind) FieldName() string { return fieldInfos[k].name }
+
+// FieldType returns the declared type of the field.
+func (k Kind) FieldType() reflect.Type { return fieldInfos[k].fieldType }
+
+// Get returns the direct child of n identified by (k, idx).
+// n's type must match k.NodeType().
+// idx must be a valid slice index, or -1 for a non-slice.
+func (k Kind) Get(n ast.Node, idx int) ast.Node {
+ if k.NodeType() != reflect.TypeOf(n) {
+ panic(fmt.Sprintf("%v.Get(%T): invalid node type", k, n))
+ }
+ v := reflect.ValueOf(n).Elem().Field(fieldInfos[k].index)
+ if idx != -1 {
+ v = v.Index(idx) // asserts valid index
+ } else {
+ // (The type assertion below asserts that v is not a slice.)
+ }
+ return v.Interface().(ast.Node) // may be nil
+}
+
+const (
+ Invalid Kind = iota // for nodes at the root of the traversal
+
+ // Kinds are sorted alphabetically.
+ // Numbering is not stable.
+ // Each is named Type_Field, where Type is the
+ // ast.Node struct type and Field is the name of the field
+
+ ArrayType_Elt
+ ArrayType_Len
+ AssignStmt_Lhs
+ AssignStmt_Rhs
+ BinaryExpr_X
+ BinaryExpr_Y
+ BlockStmt_List
+ BranchStmt_Label
+ CallExpr_Args
+ CallExpr_Fun
+ CaseClause_Body
+ CaseClause_List
+ ChanType_Value
+ CommClause_Body
+ CommClause_Comm
+ CommentGroup_List
+ CompositeLit_Elts
+ CompositeLit_Type
+ DeclStmt_Decl
+ DeferStmt_Call
+ Ellipsis_Elt
+ ExprStmt_X
+ FieldList_List
+ Field_Comment
+ Field_Doc
+ Field_Names
+ Field_Tag
+ Field_Type
+ File_Decls
+ File_Doc
+ File_Name
+ ForStmt_Body
+ ForStmt_Cond
+ ForStmt_Init
+ ForStmt_Post
+ FuncDecl_Body
+ FuncDecl_Doc
+ FuncDecl_Name
+ FuncDecl_Recv
+ FuncDecl_Type
+ FuncLit_Body
+ FuncLit_Type
+ FuncType_Params
+ FuncType_Results
+ FuncType_TypeParams
+ GenDecl_Doc
+ GenDecl_Specs
+ GoStmt_Call
+ IfStmt_Body
+ IfStmt_Cond
+ IfStmt_Else
+ IfStmt_Init
+ ImportSpec_Comment
+ ImportSpec_Doc
+ ImportSpec_Name
+ ImportSpec_Path
+ IncDecStmt_X
+ IndexExpr_Index
+ IndexExpr_X
+ IndexListExpr_Indices
+ IndexListExpr_X
+ InterfaceType_Methods
+ KeyValueExpr_Key
+ KeyValueExpr_Value
+ LabeledStmt_Label
+ LabeledStmt_Stmt
+ MapType_Key
+ MapType_Value
+ ParenExpr_X
+ RangeStmt_Body
+ RangeStmt_Key
+ RangeStmt_Value
+ RangeStmt_X
+ ReturnStmt_Results
+ SelectStmt_Body
+ SelectorExpr_Sel
+ SelectorExpr_X
+ SendStmt_Chan
+ SendStmt_Value
+ SliceExpr_High
+ SliceExpr_Low
+ SliceExpr_Max
+ SliceExpr_X
+ StarExpr_X
+ StructType_Fields
+ SwitchStmt_Body
+ SwitchStmt_Init
+ SwitchStmt_Tag
+ TypeAssertExpr_Type
+ TypeAssertExpr_X
+ TypeSpec_Comment
+ TypeSpec_Doc
+ TypeSpec_Name
+ TypeSpec_Type
+ TypeSpec_TypeParams
+ TypeSwitchStmt_Assign
+ TypeSwitchStmt_Body
+ TypeSwitchStmt_Init
+ UnaryExpr_X
+ ValueSpec_Comment
+ ValueSpec_Doc
+ ValueSpec_Names
+ ValueSpec_Type
+ ValueSpec_Values
+
+ maxKind
+)
+
+// Assert that the encoding fits in 7 bits,
+// as the inspector relies on this.
+// (We are currently at 104.)
+var _ = [1 << 7]struct{}{}[maxKind]
+
+type fieldInfo struct {
+ nodeType reflect.Type // pointer-to-struct type of ast.Node implementation
+ name string
+ index int
+ fieldType reflect.Type
+}
+
+func info[N ast.Node](fieldName string) fieldInfo {
+ nodePtrType := reflect.TypeFor[N]()
+ f, ok := nodePtrType.Elem().FieldByName(fieldName)
+ if !ok {
+ panic(fieldName)
+ }
+ return fieldInfo{nodePtrType, fieldName, f.Index[0], f.Type}
+}
+
+var fieldInfos = [...]fieldInfo{
+ Invalid: {},
+ ArrayType_Elt: info[*ast.ArrayType]("Elt"),
+ ArrayType_Len: info[*ast.ArrayType]("Len"),
+ AssignStmt_Lhs: info[*ast.AssignStmt]("Lhs"),
+ AssignStmt_Rhs: info[*ast.AssignStmt]("Rhs"),
+ BinaryExpr_X: info[*ast.BinaryExpr]("X"),
+ BinaryExpr_Y: info[*ast.BinaryExpr]("Y"),
+ BlockStmt_List: info[*ast.BlockStmt]("List"),
+ BranchStmt_Label: info[*ast.BranchStmt]("Label"),
+ CallExpr_Args: info[*ast.CallExpr]("Args"),
+ CallExpr_Fun: info[*ast.CallExpr]("Fun"),
+ CaseClause_Body: info[*ast.CaseClause]("Body"),
+ CaseClause_List: info[*ast.CaseClause]("List"),
+ ChanType_Value: info[*ast.ChanType]("Value"),
+ CommClause_Body: info[*ast.CommClause]("Body"),
+ CommClause_Comm: info[*ast.CommClause]("Comm"),
+ CommentGroup_List: info[*ast.CommentGroup]("List"),
+ CompositeLit_Elts: info[*ast.CompositeLit]("Elts"),
+ CompositeLit_Type: info[*ast.CompositeLit]("Type"),
+ DeclStmt_Decl: info[*ast.DeclStmt]("Decl"),
+ DeferStmt_Call: info[*ast.DeferStmt]("Call"),
+ Ellipsis_Elt: info[*ast.Ellipsis]("Elt"),
+ ExprStmt_X: info[*ast.ExprStmt]("X"),
+ FieldList_List: info[*ast.FieldList]("List"),
+ Field_Comment: info[*ast.Field]("Comment"),
+ Field_Doc: info[*ast.Field]("Doc"),
+ Field_Names: info[*ast.Field]("Names"),
+ Field_Tag: info[*ast.Field]("Tag"),
+ Field_Type: info[*ast.Field]("Type"),
+ File_Decls: info[*ast.File]("Decls"),
+ File_Doc: info[*ast.File]("Doc"),
+ File_Name: info[*ast.File]("Name"),
+ ForStmt_Body: info[*ast.ForStmt]("Body"),
+ ForStmt_Cond: info[*ast.ForStmt]("Cond"),
+ ForStmt_Init: info[*ast.ForStmt]("Init"),
+ ForStmt_Post: info[*ast.ForStmt]("Post"),
+ FuncDecl_Body: info[*ast.FuncDecl]("Body"),
+ FuncDecl_Doc: info[*ast.FuncDecl]("Doc"),
+ FuncDecl_Name: info[*ast.FuncDecl]("Name"),
+ FuncDecl_Recv: info[*ast.FuncDecl]("Recv"),
+ FuncDecl_Type: info[*ast.FuncDecl]("Type"),
+ FuncLit_Body: info[*ast.FuncLit]("Body"),
+ FuncLit_Type: info[*ast.FuncLit]("Type"),
+ FuncType_Params: info[*ast.FuncType]("Params"),
+ FuncType_Results: info[*ast.FuncType]("Results"),
+ FuncType_TypeParams: info[*ast.FuncType]("TypeParams"),
+ GenDecl_Doc: info[*ast.GenDecl]("Doc"),
+ GenDecl_Specs: info[*ast.GenDecl]("Specs"),
+ GoStmt_Call: info[*ast.GoStmt]("Call"),
+ IfStmt_Body: info[*ast.IfStmt]("Body"),
+ IfStmt_Cond: info[*ast.IfStmt]("Cond"),
+ IfStmt_Else: info[*ast.IfStmt]("Else"),
+ IfStmt_Init: info[*ast.IfStmt]("Init"),
+ ImportSpec_Comment: info[*ast.ImportSpec]("Comment"),
+ ImportSpec_Doc: info[*ast.ImportSpec]("Doc"),
+ ImportSpec_Name: info[*ast.ImportSpec]("Name"),
+ ImportSpec_Path: info[*ast.ImportSpec]("Path"),
+ IncDecStmt_X: info[*ast.IncDecStmt]("X"),
+ IndexExpr_Index: info[*ast.IndexExpr]("Index"),
+ IndexExpr_X: info[*ast.IndexExpr]("X"),
+ IndexListExpr_Indices: info[*ast.IndexListExpr]("Indices"),
+ IndexListExpr_X: info[*ast.IndexListExpr]("X"),
+ InterfaceType_Methods: info[*ast.InterfaceType]("Methods"),
+ KeyValueExpr_Key: info[*ast.KeyValueExpr]("Key"),
+ KeyValueExpr_Value: info[*ast.KeyValueExpr]("Value"),
+ LabeledStmt_Label: info[*ast.LabeledStmt]("Label"),
+ LabeledStmt_Stmt: info[*ast.LabeledStmt]("Stmt"),
+ MapType_Key: info[*ast.MapType]("Key"),
+ MapType_Value: info[*ast.MapType]("Value"),
+ ParenExpr_X: info[*ast.ParenExpr]("X"),
+ RangeStmt_Body: info[*ast.RangeStmt]("Body"),
+ RangeStmt_Key: info[*ast.RangeStmt]("Key"),
+ RangeStmt_Value: info[*ast.RangeStmt]("Value"),
+ RangeStmt_X: info[*ast.RangeStmt]("X"),
+ ReturnStmt_Results: info[*ast.ReturnStmt]("Results"),
+ SelectStmt_Body: info[*ast.SelectStmt]("Body"),
+ SelectorExpr_Sel: info[*ast.SelectorExpr]("Sel"),
+ SelectorExpr_X: info[*ast.SelectorExpr]("X"),
+ SendStmt_Chan: info[*ast.SendStmt]("Chan"),
+ SendStmt_Value: info[*ast.SendStmt]("Value"),
+ SliceExpr_High: info[*ast.SliceExpr]("High"),
+ SliceExpr_Low: info[*ast.SliceExpr]("Low"),
+ SliceExpr_Max: info[*ast.SliceExpr]("Max"),
+ SliceExpr_X: info[*ast.SliceExpr]("X"),
+ StarExpr_X: info[*ast.StarExpr]("X"),
+ StructType_Fields: info[*ast.StructType]("Fields"),
+ SwitchStmt_Body: info[*ast.SwitchStmt]("Body"),
+ SwitchStmt_Init: info[*ast.SwitchStmt]("Init"),
+ SwitchStmt_Tag: info[*ast.SwitchStmt]("Tag"),
+ TypeAssertExpr_Type: info[*ast.TypeAssertExpr]("Type"),
+ TypeAssertExpr_X: info[*ast.TypeAssertExpr]("X"),
+ TypeSpec_Comment: info[*ast.TypeSpec]("Comment"),
+ TypeSpec_Doc: info[*ast.TypeSpec]("Doc"),
+ TypeSpec_Name: info[*ast.TypeSpec]("Name"),
+ TypeSpec_Type: info[*ast.TypeSpec]("Type"),
+ TypeSpec_TypeParams: info[*ast.TypeSpec]("TypeParams"),
+ TypeSwitchStmt_Assign: info[*ast.TypeSwitchStmt]("Assign"),
+ TypeSwitchStmt_Body: info[*ast.TypeSwitchStmt]("Body"),
+ TypeSwitchStmt_Init: info[*ast.TypeSwitchStmt]("Init"),
+ UnaryExpr_X: info[*ast.UnaryExpr]("X"),
+ ValueSpec_Comment: info[*ast.ValueSpec]("Comment"),
+ ValueSpec_Doc: info[*ast.ValueSpec]("Doc"),
+ ValueSpec_Names: info[*ast.ValueSpec]("Names"),
+ ValueSpec_Type: info[*ast.ValueSpec]("Type"),
+ ValueSpec_Values: info[*ast.ValueSpec]("Values"),
+}
diff --git a/vendor/golang.org/x/tools/go/ast/inspector/cursor.go b/vendor/golang.org/x/tools/go/ast/inspector/cursor.go
new file mode 100644
index 0000000000..7e72d3c284
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/ast/inspector/cursor.go
@@ -0,0 +1,502 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package inspector
+
+import (
+ "fmt"
+ "go/ast"
+ "go/token"
+ "iter"
+ "reflect"
+
+ "golang.org/x/tools/go/ast/edge"
+)
+
+// A Cursor represents an [ast.Node]. It is immutable.
+//
+// Two Cursors compare equal if they represent the same node.
+//
+// Call [Inspector.Root] to obtain a valid cursor for the virtual root
+// node of the traversal.
+//
+// Use the following methods to navigate efficiently around the tree:
+// - for ancestors, use [Cursor.Parent] and [Cursor.Enclosing];
+// - for children, use [Cursor.Child], [Cursor.Children],
+// [Cursor.FirstChild], and [Cursor.LastChild];
+// - for siblings, use [Cursor.PrevSibling] and [Cursor.NextSibling];
+// - for descendants, use [Cursor.FindByPos], [Cursor.FindNode],
+// [Cursor.Inspect], and [Cursor.Preorder].
+//
+// Use the [Cursor.ChildAt] and [Cursor.ParentEdge] methods for
+// information about the edges in a tree: which field (and slice
+// element) of the parent node holds the child.
+type Cursor struct {
+ in *Inspector
+ index int32 // index of push node; -1 for virtual root node
+}
+
+// Root returns a cursor for the virtual root node,
+// whose children are the files provided to [New].
+//
+// Its [Cursor.Node] method return nil.
+func (in *Inspector) Root() Cursor {
+ return Cursor{in, -1}
+}
+
+// At returns the cursor at the specified index in the traversal,
+// which must have been obtained from [Cursor.Index] on a Cursor
+// belonging to the same Inspector (see [Cursor.Inspector]).
+func (in *Inspector) At(index int32) Cursor {
+ if index < 0 {
+ panic("negative index")
+ }
+ if int(index) >= len(in.events) {
+ panic("index out of range for this inspector")
+ }
+ if in.events[index].index < index {
+ panic("invalid index") // (a push, not a pop)
+ }
+ return Cursor{in, index}
+}
+
+// Inspector returns the cursor's Inspector.
+func (c Cursor) Inspector() *Inspector { return c.in }
+
+// Index returns the index of this cursor position within the package.
+//
+// Clients should not assume anything about the numeric Index value
+// except that it increases monotonically throughout the traversal.
+// It is provided for use with [At].
+//
+// Index must not be called on the Root node.
+func (c Cursor) Index() int32 {
+ if c.index < 0 {
+ panic("Index called on Root node")
+ }
+ return c.index
+}
+
+// Node returns the node at the current cursor position,
+// or nil for the cursor returned by [Inspector.Root].
+func (c Cursor) Node() ast.Node {
+ if c.index < 0 {
+ return nil
+ }
+ return c.in.events[c.index].node
+}
+
+// String returns information about the cursor's node, if any.
+func (c Cursor) String() string {
+ if c.in == nil {
+ return "(invalid)"
+ }
+ if c.index < 0 {
+ return "(root)"
+ }
+ return reflect.TypeOf(c.Node()).String()
+}
+
+// indices return the [start, end) half-open interval of event indices.
+func (c Cursor) indices() (int32, int32) {
+ if c.index < 0 {
+ return 0, int32(len(c.in.events)) // root: all events
+ } else {
+ return c.index, c.in.events[c.index].index + 1 // just one subtree
+ }
+}
+
+// Preorder returns an iterator over the nodes of the subtree
+// represented by c in depth-first order. Each node in the sequence is
+// represented by a Cursor that allows access to the Node, but may
+// also be used to start a new traversal, or to obtain the stack of
+// nodes enclosing the cursor.
+//
+// The traversal sequence is determined by [ast.Inspect]. The types
+// argument, if non-empty, enables type-based filtering of events. The
+// function f if is called only for nodes whose type matches an
+// element of the types slice.
+//
+// If you need control over descent into subtrees,
+// or need both pre- and post-order notifications, use [Cursor.Inspect]
+func (c Cursor) Preorder(types ...ast.Node) iter.Seq[Cursor] {
+ mask := maskOf(types)
+
+ return func(yield func(Cursor) bool) {
+ events := c.in.events
+
+ for i, limit := c.indices(); i < limit; {
+ ev := events[i]
+ if ev.index > i { // push?
+ if ev.typ&mask != 0 && !yield(Cursor{c.in, i}) {
+ break
+ }
+ pop := ev.index
+ if events[pop].typ&mask == 0 {
+ // Subtree does not contain types: skip.
+ i = pop + 1
+ continue
+ }
+ }
+ i++
+ }
+ }
+}
+
+// Inspect visits the nodes of the subtree represented by c in
+// depth-first order. It calls f(n) for each node n before it
+// visits n's children. If f returns true, Inspect invokes f
+// recursively for each of the non-nil children of the node.
+//
+// Each node is represented by a Cursor that allows access to the
+// Node, but may also be used to start a new traversal, or to obtain
+// the stack of nodes enclosing the cursor.
+//
+// The complete traversal sequence is determined by [ast.Inspect].
+// The types argument, if non-empty, enables type-based filtering of
+// events. The function f if is called only for nodes whose type
+// matches an element of the types slice.
+func (c Cursor) Inspect(types []ast.Node, f func(c Cursor) (descend bool)) {
+ mask := maskOf(types)
+ events := c.in.events
+ for i, limit := c.indices(); i < limit; {
+ ev := events[i]
+ if ev.index > i {
+ // push
+ pop := ev.index
+ if ev.typ&mask != 0 && !f(Cursor{c.in, i}) ||
+ events[pop].typ&mask == 0 {
+ // The user opted not to descend, or the
+ // subtree does not contain types:
+ // skip past the pop.
+ i = pop + 1
+ continue
+ }
+ }
+ i++
+ }
+}
+
+// Enclosing returns an iterator over the nodes enclosing the current
+// current node, starting with the Cursor itself.
+//
+// Enclosing must not be called on the Root node (whose [Cursor.Node] returns nil).
+//
+// The types argument, if non-empty, enables type-based filtering of
+// events: the sequence includes only enclosing nodes whose type
+// matches an element of the types slice.
+func (c Cursor) Enclosing(types ...ast.Node) iter.Seq[Cursor] {
+ if c.index < 0 {
+ panic("Cursor.Enclosing called on Root node")
+ }
+
+ mask := maskOf(types)
+
+ return func(yield func(Cursor) bool) {
+ events := c.in.events
+ for i := c.index; i >= 0; i = events[i].parent {
+ if events[i].typ&mask != 0 && !yield(Cursor{c.in, i}) {
+ break
+ }
+ }
+ }
+}
+
+// Parent returns the parent of the current node.
+//
+// Parent must not be called on the Root node (whose [Cursor.Node] returns nil).
+func (c Cursor) Parent() Cursor {
+ if c.index < 0 {
+ panic("Cursor.Parent called on Root node")
+ }
+
+ return Cursor{c.in, c.in.events[c.index].parent}
+}
+
+// ParentEdge returns the identity of the field in the parent node
+// that holds this cursor's node, and if it is a list, the index within it.
+//
+// For example, f(x, y) is a CallExpr whose three children are Idents.
+// f has edge kind [edge.CallExpr_Fun] and index -1.
+// x and y have kind [edge.CallExpr_Args] and indices 0 and 1, respectively.
+//
+// If called on a child of the Root node, it returns ([edge.Invalid], -1).
+//
+// ParentEdge must not be called on the Root node (whose [Cursor.Node] returns nil).
+func (c Cursor) ParentEdge() (edge.Kind, int) {
+ if c.index < 0 {
+ panic("Cursor.ParentEdge called on Root node")
+ }
+ events := c.in.events
+ pop := events[c.index].index
+ return unpackEdgeKindAndIndex(events[pop].parent)
+}
+
+// ChildAt returns the cursor for the child of the
+// current node identified by its edge and index.
+// The index must be -1 if the edge.Kind is not a slice.
+// The indicated child node must exist.
+//
+// ChildAt must not be called on the Root node (whose [Cursor.Node] returns nil).
+//
+// Invariant: c.Parent().ChildAt(c.ParentEdge()) == c.
+func (c Cursor) ChildAt(k edge.Kind, idx int) Cursor {
+ target := packEdgeKindAndIndex(k, idx)
+
+ // Unfortunately there's no shortcut to looping.
+ events := c.in.events
+ i := c.index + 1
+ for {
+ pop := events[i].index
+ if pop < i {
+ break
+ }
+ if events[pop].parent == target {
+ return Cursor{c.in, i}
+ }
+ i = pop + 1
+ }
+ panic(fmt.Sprintf("ChildAt(%v, %d): no such child of %v", k, idx, c))
+}
+
+// Child returns the cursor for n, which must be a direct child of c's Node.
+//
+// Child must not be called on the Root node (whose [Cursor.Node] returns nil).
+func (c Cursor) Child(n ast.Node) Cursor {
+ if c.index < 0 {
+ panic("Cursor.Child called on Root node")
+ }
+
+ if false {
+ // reference implementation
+ for child := range c.Children() {
+ if child.Node() == n {
+ return child
+ }
+ }
+
+ } else {
+ // optimized implementation
+ events := c.in.events
+ for i := c.index + 1; events[i].index > i; i = events[i].index + 1 {
+ if events[i].node == n {
+ return Cursor{c.in, i}
+ }
+ }
+ }
+ panic(fmt.Sprintf("Child(%T): not a child of %v", n, c))
+}
+
+// NextSibling returns the cursor for the next sibling node in the same list
+// (for example, of files, decls, specs, statements, fields, or expressions) as
+// the current node. It returns (zero, false) if the node is the last node in
+// the list, or is not part of a list.
+//
+// NextSibling must not be called on the Root node.
+//
+// See note at [Cursor.Children].
+func (c Cursor) NextSibling() (Cursor, bool) {
+ if c.index < 0 {
+ panic("Cursor.NextSibling called on Root node")
+ }
+
+ events := c.in.events
+ i := events[c.index].index + 1 // after corresponding pop
+ if i < int32(len(events)) {
+ if events[i].index > i { // push?
+ return Cursor{c.in, i}, true
+ }
+ }
+ return Cursor{}, false
+}
+
+// PrevSibling returns the cursor for the previous sibling node in the
+// same list (for example, of files, decls, specs, statements, fields,
+// or expressions) as the current node. It returns zero if the node is
+// the first node in the list, or is not part of a list.
+//
+// It must not be called on the Root node.
+//
+// See note at [Cursor.Children].
+func (c Cursor) PrevSibling() (Cursor, bool) {
+ if c.index < 0 {
+ panic("Cursor.PrevSibling called on Root node")
+ }
+
+ events := c.in.events
+ i := c.index - 1
+ if i >= 0 {
+ if j := events[i].index; j < i { // pop?
+ return Cursor{c.in, j}, true
+ }
+ }
+ return Cursor{}, false
+}
+
+// FirstChild returns the first direct child of the current node,
+// or zero if it has no children.
+func (c Cursor) FirstChild() (Cursor, bool) {
+ events := c.in.events
+ i := c.index + 1 // i=0 if c is root
+ if i < int32(len(events)) && events[i].index > i { // push?
+ return Cursor{c.in, i}, true
+ }
+ return Cursor{}, false
+}
+
+// LastChild returns the last direct child of the current node,
+// or zero if it has no children.
+func (c Cursor) LastChild() (Cursor, bool) {
+ events := c.in.events
+ if c.index < 0 { // root?
+ if len(events) > 0 {
+ // return push of final event (a pop)
+ return Cursor{c.in, events[len(events)-1].index}, true
+ }
+ } else {
+ j := events[c.index].index - 1 // before corresponding pop
+ // Inv: j == c.index if c has no children
+ // or j is last child's pop.
+ if j > c.index { // c has children
+ return Cursor{c.in, events[j].index}, true
+ }
+ }
+ return Cursor{}, false
+}
+
+// Children returns an iterator over the direct children of the
+// current node, if any.
+//
+// When using Children, NextChild, and PrevChild, bear in mind that a
+// Node's children may come from different fields, some of which may
+// be lists of nodes without a distinguished intervening container
+// such as [ast.BlockStmt].
+//
+// For example, [ast.CaseClause] has a field List of expressions and a
+// field Body of statements, so the children of a CaseClause are a mix
+// of expressions and statements. Other nodes that have "uncontained"
+// list fields include:
+//
+// - [ast.ValueSpec] (Names, Values)
+// - [ast.CompositeLit] (Type, Elts)
+// - [ast.IndexListExpr] (X, Indices)
+// - [ast.CallExpr] (Fun, Args)
+// - [ast.AssignStmt] (Lhs, Rhs)
+//
+// So, do not assume that the previous sibling of an ast.Stmt is also
+// an ast.Stmt, or if it is, that they are executed sequentially,
+// unless you have established that, say, its parent is a BlockStmt
+// or its [Cursor.ParentEdge] is [edge.BlockStmt_List].
+// For example, given "for S1; ; S2 {}", the predecessor of S2 is S1,
+// even though they are not executed in sequence.
+func (c Cursor) Children() iter.Seq[Cursor] {
+ return func(yield func(Cursor) bool) {
+ c, ok := c.FirstChild()
+ for ok && yield(c) {
+ c, ok = c.NextSibling()
+ }
+ }
+}
+
+// Contains reports whether c contains or is equal to c2.
+//
+// Both Cursors must belong to the same [Inspector];
+// neither may be its Root node.
+func (c Cursor) Contains(c2 Cursor) bool {
+ if c.in != c2.in {
+ panic("different inspectors")
+ }
+ events := c.in.events
+ return c.index <= c2.index && events[c2.index].index <= events[c.index].index
+}
+
+// FindNode returns the cursor for node n if it belongs to the subtree
+// rooted at c. It returns zero if n is not found.
+func (c Cursor) FindNode(n ast.Node) (Cursor, bool) {
+
+ // FindNode is equivalent to this code,
+ // but more convenient and 15-20% faster:
+ if false {
+ for candidate := range c.Preorder(n) {
+ if candidate.Node() == n {
+ return candidate, true
+ }
+ }
+ return Cursor{}, false
+ }
+
+ // TODO(adonovan): opt: should we assume Node.Pos is accurate
+ // and combine type-based filtering with position filtering
+ // like FindByPos?
+
+ mask := maskOf([]ast.Node{n})
+ events := c.in.events
+
+ for i, limit := c.indices(); i < limit; i++ {
+ ev := events[i]
+ if ev.index > i { // push?
+ if ev.typ&mask != 0 && ev.node == n {
+ return Cursor{c.in, i}, true
+ }
+ pop := ev.index
+ if events[pop].typ&mask == 0 {
+ // Subtree does not contain type of n: skip.
+ i = pop
+ }
+ }
+ }
+ return Cursor{}, false
+}
+
+// FindByPos returns the cursor for the innermost node n in the tree
+// rooted at c such that n.Pos() <= start && end <= n.End().
+// (For an *ast.File, it uses the bounds n.FileStart-n.FileEnd.)
+//
+// It returns zero if none is found.
+// Precondition: start <= end.
+//
+// See also [astutil.PathEnclosingInterval], which
+// tolerates adjoining whitespace.
+func (c Cursor) FindByPos(start, end token.Pos) (Cursor, bool) {
+ if end < start {
+ panic("end < start")
+ }
+ events := c.in.events
+
+ // This algorithm could be implemented using c.Inspect,
+ // but it is about 2.5x slower.
+
+ best := int32(-1) // push index of latest (=innermost) node containing range
+ for i, limit := c.indices(); i < limit; i++ {
+ ev := events[i]
+ if ev.index > i { // push?
+ n := ev.node
+ var nodeEnd token.Pos
+ if file, ok := n.(*ast.File); ok {
+ nodeEnd = file.FileEnd
+ // Note: files may be out of Pos order.
+ if file.FileStart > start {
+ i = ev.index // disjoint, after; skip to next file
+ continue
+ }
+ } else {
+ nodeEnd = n.End()
+ if n.Pos() > start {
+ break // disjoint, after; stop
+ }
+ }
+ // Inv: node.{Pos,FileStart} <= start
+ if end <= nodeEnd {
+ // node fully contains target range
+ best = i
+ } else if nodeEnd < start {
+ i = ev.index // disjoint, before; skip forward
+ }
+ }
+ }
+ if best >= 0 {
+ return Cursor{c.in, best}, true
+ }
+ return Cursor{}, false
+}
diff --git a/vendor/golang.org/x/tools/go/ast/inspector/inspector.go b/vendor/golang.org/x/tools/go/ast/inspector/inspector.go
new file mode 100644
index 0000000000..a703cdfcf9
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/ast/inspector/inspector.go
@@ -0,0 +1,311 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package inspector provides helper functions for traversal over the
+// syntax trees of a package, including node filtering by type, and
+// materialization of the traversal stack.
+//
+// During construction, the inspector does a complete traversal and
+// builds a list of push/pop events and their node type. Subsequent
+// method calls that request a traversal scan this list, rather than walk
+// the AST, and perform type filtering using efficient bit sets.
+// This representation is sometimes called a "balanced parenthesis tree."
+//
+// Experiments suggest the inspector's traversals are about 2.5x faster
+// than [ast.Inspect], but it may take around 5 traversals for this
+// benefit to amortize the inspector's construction cost.
+// If efficiency is the primary concern, do not use Inspector for
+// one-off traversals.
+//
+// The [Cursor] type provides a more flexible API for efficient
+// navigation of syntax trees in all four "cardinal directions". For
+// example, traversals may be nested, so you can find each node of
+// type A and then search within it for nodes of type B. Or you can
+// traverse from a node to its immediate neighbors: its parent, its
+// previous and next sibling, or its first and last child. We
+// recommend using methods of Cursor in preference to Inspector where
+// possible.
+package inspector
+
+// There are four orthogonal features in a traversal:
+// 1 type filtering
+// 2 pruning
+// 3 postorder calls to f
+// 4 stack
+// Rather than offer all of them in the API,
+// only a few combinations are exposed:
+// - Preorder is the fastest and has fewest features,
+// but is the most commonly needed traversal.
+// - Nodes and WithStack both provide pruning and postorder calls,
+// even though few clients need it, because supporting two versions
+// is not justified.
+// More combinations could be supported by expressing them as
+// wrappers around a more generic traversal, but this was measured
+// and found to degrade performance significantly (30%).
+
+import (
+ "go/ast"
+
+ "golang.org/x/tools/go/ast/edge"
+)
+
+// An Inspector provides methods for inspecting
+// (traversing) the syntax trees of a package.
+type Inspector struct {
+ events []event
+}
+
+func packEdgeKindAndIndex(ek edge.Kind, index int) int32 {
+ return int32(uint32(index+1)<<7 | uint32(ek))
+}
+
+// unpackEdgeKindAndIndex unpacks the edge kind and edge index (within
+// an []ast.Node slice) from the parent field of a pop event.
+func unpackEdgeKindAndIndex(x int32) (edge.Kind, int) {
+ // The "parent" field of a pop node holds the
+ // edge Kind in the lower 7 bits and the index+1
+ // in the upper 25.
+ return edge.Kind(x & 0x7f), int(x>>7) - 1
+}
+
+// New returns an Inspector for the specified syntax trees.
+func New(files []*ast.File) *Inspector {
+ return &Inspector{traverse(files)}
+}
+
+// An event represents a push or a pop
+// of an ast.Node during a traversal.
+type event struct {
+ node ast.Node
+ typ uint64 // typeOf(node) on push event, or union of typ strictly between push and pop events on pop events
+ index int32 // index of corresponding push or pop event
+ parent int32 // index of parent's push node (push nodes only), or packed edge kind/index (pop nodes only)
+}
+
+// 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
+// n's children.
+//
+// The complete traversal sequence is determined by [ast.Inspect].
+// The types argument, if non-empty, enables type-based filtering of
+// events. The function f is called only for nodes whose type
+// matches an element of the types slice.
+//
+// The [Cursor.Preorder] method provides a richer alternative interface.
+// Example:
+//
+// for c := range in.Root().Preorder(types) { ... }
+func (in *Inspector) Preorder(types []ast.Node, f func(ast.Node)) {
+ // Because it avoids postorder calls to f, and the pruning
+ // check, Preorder is almost twice as fast as Nodes. The two
+ // features seem to contribute similar slowdowns (~1.4x each).
+
+ // This function is equivalent to the PreorderSeq call below,
+ // but to avoid the additional dynamic call (which adds 13-35%
+ // to the benchmarks), we expand it out.
+ //
+ // in.PreorderSeq(types...)(func(n ast.Node) bool {
+ // f(n)
+ // return true
+ // })
+
+ mask := maskOf(types)
+ for i := int32(0); i < int32(len(in.events)); {
+ ev := in.events[i]
+ if ev.index > i {
+ // push
+ if ev.typ&mask != 0 {
+ f(ev.node)
+ }
+ pop := ev.index
+ if in.events[pop].typ&mask == 0 {
+ // Subtrees do not contain types: skip them and pop.
+ i = pop + 1
+ continue
+ }
+ }
+ i++
+ }
+}
+
+// Nodes visits the nodes of the files supplied to New in depth-first
+// order. It calls f(n, true) for each node n before it visits n's
+// children. If f returns true, Nodes invokes f recursively for each
+// of the non-nil children of the node, followed by a call of
+// f(n, false).
+//
+// The complete traversal sequence is determined by [ast.Inspect].
+// The types argument, if non-empty, enables type-based filtering of
+// events. The function f if is called only for nodes whose type
+// matches an element of the types slice.
+//
+// The [Cursor.Inspect] method provides a richer alternative interface.
+// Example:
+//
+// in.Root().Inspect(types, func(c Cursor) bool {
+// ...
+// return true
+// }
+func (in *Inspector) Nodes(types []ast.Node, f func(n ast.Node, push bool) (proceed bool)) {
+ mask := maskOf(types)
+ for i := int32(0); i < int32(len(in.events)); {
+ ev := in.events[i]
+ if ev.index > i {
+ // push
+ pop := ev.index
+ if ev.typ&mask != 0 {
+ if !f(ev.node, true) {
+ i = pop + 1 // jump to corresponding pop + 1
+ continue
+ }
+ }
+ if in.events[pop].typ&mask == 0 {
+ // Subtrees do not contain types: skip them.
+ i = pop
+ continue
+ }
+ } else {
+ // pop
+ push := ev.index
+ if in.events[push].typ&mask != 0 {
+ f(ev.node, false)
+ }
+ }
+ i++
+ }
+}
+
+// WithStack visits nodes in a similar manner to Nodes, but it
+// supplies each call to f an additional argument, the current
+// traversal stack. The stack's first element is the outermost node,
+// an *ast.File; its last is the innermost, n.
+//
+// The [Cursor.Inspect] method provides a richer alternative interface.
+// Example:
+//
+// in.Root().Inspect(types, func(c Cursor) bool {
+// stack := slices.Collect(c.Enclosing())
+// ...
+// return true
+// })
+func (in *Inspector) WithStack(types []ast.Node, f func(n ast.Node, push bool, stack []ast.Node) (proceed bool)) {
+ mask := maskOf(types)
+ var stack []ast.Node
+ for i := int32(0); i < int32(len(in.events)); {
+ ev := in.events[i]
+ if ev.index > i {
+ // push
+ pop := ev.index
+ stack = append(stack, ev.node)
+ if ev.typ&mask != 0 {
+ if !f(ev.node, true, stack) {
+ i = pop + 1
+ stack = stack[:len(stack)-1]
+ continue
+ }
+ }
+ if in.events[pop].typ&mask == 0 {
+ // Subtrees does not contain types: skip them.
+ i = pop
+ continue
+ }
+ } else {
+ // pop
+ push := ev.index
+ if in.events[push].typ&mask != 0 {
+ f(ev.node, false, stack)
+ }
+ stack = stack[:len(stack)-1]
+ }
+ i++
+ }
+}
+
+// traverse builds the table of events representing a traversal.
+func traverse(files []*ast.File) []event {
+ // Preallocate approximate number of events
+ // based on source file extent of the declarations.
+ // (We use End-Pos not FileStart-FileEnd to neglect
+ // the effect of long doc comments.)
+ // This makes traverse faster by 4x (!).
+ var extent int
+ for _, f := range files {
+ extent += int(f.End() - f.Pos())
+ }
+ // This estimate is based on the net/http package.
+ capacity := min(extent*33/100, 1e6) // impose some reasonable maximum (1M)
+
+ v := &visitor{
+ events: make([]event, 0, capacity),
+ stack: []item{{index: -1}}, // include an extra event so file nodes have a parent
+ }
+ for _, file := range files {
+ walk(v, edge.Invalid, -1, file)
+ }
+ return v.events
+}
+
+type visitor struct {
+ events []event
+ stack []item
+}
+
+type item struct {
+ index int32 // index of current node's push event
+ parentIndex int32 // index of parent node's push event
+ typAccum uint64 // accumulated type bits of current node's descendants
+ edgeKindAndIndex int32 // edge.Kind and index, bit packed
+}
+
+func (v *visitor) push(ek edge.Kind, eindex int, node ast.Node) {
+ var (
+ index = int32(len(v.events))
+ parentIndex = v.stack[len(v.stack)-1].index
+ )
+ v.events = append(v.events, event{
+ node: node,
+ parent: parentIndex,
+ typ: typeOf(node),
+ index: 0, // (pop index is set later by visitor.pop)
+ })
+ v.stack = append(v.stack, item{
+ index: index,
+ parentIndex: parentIndex,
+ edgeKindAndIndex: packEdgeKindAndIndex(ek, eindex),
+ })
+
+ // 2B nodes ought to be enough for anyone!
+ if int32(len(v.events)) < 0 {
+ panic("event index exceeded int32")
+ }
+
+ // 32M elements in an []ast.Node ought to be enough for anyone!
+ if ek2, eindex2 := unpackEdgeKindAndIndex(packEdgeKindAndIndex(ek, eindex)); ek2 != ek || eindex2 != eindex {
+ panic("Node slice index exceeded uint25")
+ }
+}
+
+func (v *visitor) pop(node ast.Node) {
+ top := len(v.stack) - 1
+ current := v.stack[top]
+
+ push := &v.events[current.index]
+ parent := &v.stack[top-1]
+
+ push.index = int32(len(v.events)) // make push event refer to pop
+ parent.typAccum |= current.typAccum | push.typ // accumulate type bits into parent
+
+ v.stack = v.stack[:top]
+
+ v.events = append(v.events, event{
+ node: node,
+ typ: current.typAccum,
+ index: current.index,
+ parent: current.edgeKindAndIndex, // see [unpackEdgeKindAndIndex]
+ })
+}
diff --git a/vendor/golang.org/x/tools/go/ast/inspector/iter.go b/vendor/golang.org/x/tools/go/ast/inspector/iter.go
new file mode 100644
index 0000000000..c576dc70ac
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/ast/inspector/iter.go
@@ -0,0 +1,85 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build go1.23
+
+package inspector
+
+import (
+ "go/ast"
+ "iter"
+)
+
+// PreorderSeq returns an iterator that visits all the
+// nodes of the files supplied to New in depth-first order.
+// It visits each node n before n's children.
+// The complete traversal sequence is determined by ast.Inspect.
+//
+// The types argument, if non-empty, enables type-based
+// filtering of events: only nodes whose type matches an
+// element of the types slice are included in the sequence.
+func (in *Inspector) PreorderSeq(types ...ast.Node) iter.Seq[ast.Node] {
+
+ // This implementation is identical to Preorder,
+ // except that it supports breaking out of the loop.
+
+ return func(yield func(ast.Node) bool) {
+ mask := maskOf(types)
+ for i := int32(0); i < int32(len(in.events)); {
+ ev := in.events[i]
+ if ev.index > i {
+ // push
+ if ev.typ&mask != 0 {
+ if !yield(ev.node) {
+ break
+ }
+ }
+ pop := ev.index
+ if in.events[pop].typ&mask == 0 {
+ // Subtrees do not contain types: skip them and pop.
+ i = pop + 1
+ continue
+ }
+ }
+ i++
+ }
+ }
+}
+
+// All[N] returns an iterator over all the nodes of type N.
+// N must be a pointer-to-struct type that implements ast.Node.
+//
+// Example:
+//
+// for call := range All[*ast.CallExpr](in) { ... }
+func All[N interface {
+ *S
+ ast.Node
+}, S any](in *Inspector) iter.Seq[N] {
+
+ // To avoid additional dynamic call overheads,
+ // we duplicate rather than call the logic of PreorderSeq.
+
+ mask := typeOf((N)(nil))
+ return func(yield func(N) bool) {
+ for i := int32(0); i < int32(len(in.events)); {
+ ev := in.events[i]
+ if ev.index > i {
+ // push
+ if ev.typ&mask != 0 {
+ if !yield(ev.node.(N)) {
+ break
+ }
+ }
+ pop := ev.index
+ if in.events[pop].typ&mask == 0 {
+ // Subtrees do not contain types: skip them and pop.
+ i = pop + 1
+ continue
+ }
+ }
+ i++
+ }
+ }
+}
diff --git a/vendor/golang.org/x/tools/go/ast/inspector/typeof.go b/vendor/golang.org/x/tools/go/ast/inspector/typeof.go
new file mode 100644
index 0000000000..9852331a3d
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/ast/inspector/typeof.go
@@ -0,0 +1,227 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package inspector
+
+// This file defines func typeOf(ast.Node) uint64.
+//
+// The initial map-based implementation was too slow;
+// see https://go-review.googlesource.com/c/tools/+/135655/1/go/ast/inspector/inspector.go#196
+
+import (
+ "go/ast"
+ "math"
+)
+
+const (
+ nArrayType = iota
+ nAssignStmt
+ nBadDecl
+ nBadExpr
+ nBadStmt
+ nBasicLit
+ nBinaryExpr
+ nBlockStmt
+ nBranchStmt
+ nCallExpr
+ nCaseClause
+ nChanType
+ nCommClause
+ nComment
+ nCommentGroup
+ nCompositeLit
+ nDeclStmt
+ nDeferStmt
+ nEllipsis
+ nEmptyStmt
+ nExprStmt
+ nField
+ nFieldList
+ nFile
+ nForStmt
+ nFuncDecl
+ nFuncLit
+ nFuncType
+ nGenDecl
+ nGoStmt
+ nIdent
+ nIfStmt
+ nImportSpec
+ nIncDecStmt
+ nIndexExpr
+ nIndexListExpr
+ nInterfaceType
+ nKeyValueExpr
+ nLabeledStmt
+ nMapType
+ nPackage
+ nParenExpr
+ nRangeStmt
+ nReturnStmt
+ nSelectStmt
+ nSelectorExpr
+ nSendStmt
+ nSliceExpr
+ nStarExpr
+ nStructType
+ nSwitchStmt
+ nTypeAssertExpr
+ nTypeSpec
+ nTypeSwitchStmt
+ nUnaryExpr
+ nValueSpec
+)
+
+// typeOf returns a distinct single-bit value that represents the type of n.
+//
+// Various implementations were benchmarked with BenchmarkNewInspector:
+//
+// GOGC=off
+// - type switch 4.9-5.5ms 2.1ms
+// - binary search over a sorted list of types 5.5-5.9ms 2.5ms
+// - linear scan, frequency-ordered list 5.9-6.1ms 2.7ms
+// - linear scan, unordered list 6.4ms 2.7ms
+// - hash table 6.5ms 3.1ms
+//
+// A perfect hash seemed like overkill.
+//
+// The compiler's switch statement is the clear winner
+// as it produces a binary tree in code,
+// with constant conditions and good branch prediction.
+// (Sadly it is the most verbose in source code.)
+// Binary search suffered from poor branch prediction.
+func typeOf(n ast.Node) uint64 {
+ // Fast path: nearly half of all nodes are identifiers.
+ if _, ok := n.(*ast.Ident); ok {
+ return 1 << nIdent
+ }
+
+ // These cases include all nodes encountered by ast.Inspect.
+ switch n.(type) {
+ case *ast.ArrayType:
+ return 1 << nArrayType
+ case *ast.AssignStmt:
+ return 1 << nAssignStmt
+ case *ast.BadDecl:
+ return 1 << nBadDecl
+ case *ast.BadExpr:
+ return 1 << nBadExpr
+ case *ast.BadStmt:
+ return 1 << nBadStmt
+ case *ast.BasicLit:
+ return 1 << nBasicLit
+ case *ast.BinaryExpr:
+ return 1 << nBinaryExpr
+ case *ast.BlockStmt:
+ return 1 << nBlockStmt
+ case *ast.BranchStmt:
+ return 1 << nBranchStmt
+ case *ast.CallExpr:
+ return 1 << nCallExpr
+ case *ast.CaseClause:
+ return 1 << nCaseClause
+ case *ast.ChanType:
+ return 1 << nChanType
+ case *ast.CommClause:
+ return 1 << nCommClause
+ case *ast.Comment:
+ return 1 << nComment
+ case *ast.CommentGroup:
+ return 1 << nCommentGroup
+ case *ast.CompositeLit:
+ return 1 << nCompositeLit
+ case *ast.DeclStmt:
+ return 1 << nDeclStmt
+ case *ast.DeferStmt:
+ return 1 << nDeferStmt
+ case *ast.Ellipsis:
+ return 1 << nEllipsis
+ case *ast.EmptyStmt:
+ return 1 << nEmptyStmt
+ case *ast.ExprStmt:
+ return 1 << nExprStmt
+ case *ast.Field:
+ return 1 << nField
+ case *ast.FieldList:
+ return 1 << nFieldList
+ case *ast.File:
+ return 1 << nFile
+ case *ast.ForStmt:
+ return 1 << nForStmt
+ case *ast.FuncDecl:
+ return 1 << nFuncDecl
+ case *ast.FuncLit:
+ return 1 << nFuncLit
+ case *ast.FuncType:
+ return 1 << nFuncType
+ case *ast.GenDecl:
+ return 1 << nGenDecl
+ case *ast.GoStmt:
+ return 1 << nGoStmt
+ case *ast.Ident:
+ return 1 << nIdent
+ case *ast.IfStmt:
+ return 1 << nIfStmt
+ case *ast.ImportSpec:
+ return 1 << nImportSpec
+ case *ast.IncDecStmt:
+ return 1 << nIncDecStmt
+ case *ast.IndexExpr:
+ return 1 << nIndexExpr
+ case *ast.IndexListExpr:
+ return 1 << nIndexListExpr
+ case *ast.InterfaceType:
+ return 1 << nInterfaceType
+ case *ast.KeyValueExpr:
+ return 1 << nKeyValueExpr
+ case *ast.LabeledStmt:
+ return 1 << nLabeledStmt
+ case *ast.MapType:
+ return 1 << nMapType
+ case *ast.Package:
+ return 1 << nPackage
+ case *ast.ParenExpr:
+ return 1 << nParenExpr
+ case *ast.RangeStmt:
+ return 1 << nRangeStmt
+ case *ast.ReturnStmt:
+ return 1 << nReturnStmt
+ case *ast.SelectStmt:
+ return 1 << nSelectStmt
+ case *ast.SelectorExpr:
+ return 1 << nSelectorExpr
+ case *ast.SendStmt:
+ return 1 << nSendStmt
+ case *ast.SliceExpr:
+ return 1 << nSliceExpr
+ case *ast.StarExpr:
+ return 1 << nStarExpr
+ case *ast.StructType:
+ return 1 << nStructType
+ case *ast.SwitchStmt:
+ return 1 << nSwitchStmt
+ case *ast.TypeAssertExpr:
+ return 1 << nTypeAssertExpr
+ case *ast.TypeSpec:
+ return 1 << nTypeSpec
+ case *ast.TypeSwitchStmt:
+ return 1 << nTypeSwitchStmt
+ case *ast.UnaryExpr:
+ return 1 << nUnaryExpr
+ case *ast.ValueSpec:
+ return 1 << nValueSpec
+ }
+ return 0
+}
+
+func maskOf(nodes []ast.Node) uint64 {
+ if len(nodes) == 0 {
+ return math.MaxUint64 // match all node types
+ }
+ var mask uint64
+ for _, n := range nodes {
+ mask |= typeOf(n)
+ }
+ return mask
+}
diff --git a/vendor/golang.org/x/tools/go/ast/inspector/walk.go b/vendor/golang.org/x/tools/go/ast/inspector/walk.go
new file mode 100644
index 0000000000..5f1c93c8a7
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/ast/inspector/walk.go
@@ -0,0 +1,341 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package inspector
+
+// This file is a fork of ast.Inspect to reduce unnecessary dynamic
+// calls and to gather edge information.
+//
+// Consistency with the original is ensured by TestInspectAllNodes.
+
+import (
+ "fmt"
+ "go/ast"
+
+ "golang.org/x/tools/go/ast/edge"
+)
+
+func walkList[N ast.Node](v *visitor, ek edge.Kind, list []N) {
+ for i, node := range list {
+ walk(v, ek, i, node)
+ }
+}
+
+func walk(v *visitor, ek edge.Kind, index int, node ast.Node) {
+ v.push(ek, index, node)
+
+ // walk children
+ // (the order of the cases matches the order
+ // of the corresponding node types in ast.go)
+ switch n := node.(type) {
+ // Comments and fields
+ case *ast.Comment:
+ // nothing to do
+
+ case *ast.CommentGroup:
+ walkList(v, edge.CommentGroup_List, n.List)
+
+ case *ast.Field:
+ if n.Doc != nil {
+ walk(v, edge.Field_Doc, -1, n.Doc)
+ }
+ walkList(v, edge.Field_Names, n.Names)
+ if n.Type != nil {
+ walk(v, edge.Field_Type, -1, n.Type)
+ }
+ if n.Tag != nil {
+ walk(v, edge.Field_Tag, -1, n.Tag)
+ }
+ if n.Comment != nil {
+ walk(v, edge.Field_Comment, -1, n.Comment)
+ }
+
+ case *ast.FieldList:
+ walkList(v, edge.FieldList_List, n.List)
+
+ // Expressions
+ case *ast.BadExpr, *ast.Ident, *ast.BasicLit:
+ // nothing to do
+
+ case *ast.Ellipsis:
+ if n.Elt != nil {
+ walk(v, edge.Ellipsis_Elt, -1, n.Elt)
+ }
+
+ case *ast.FuncLit:
+ walk(v, edge.FuncLit_Type, -1, n.Type)
+ walk(v, edge.FuncLit_Body, -1, n.Body)
+
+ case *ast.CompositeLit:
+ if n.Type != nil {
+ walk(v, edge.CompositeLit_Type, -1, n.Type)
+ }
+ walkList(v, edge.CompositeLit_Elts, n.Elts)
+
+ case *ast.ParenExpr:
+ walk(v, edge.ParenExpr_X, -1, n.X)
+
+ case *ast.SelectorExpr:
+ walk(v, edge.SelectorExpr_X, -1, n.X)
+ walk(v, edge.SelectorExpr_Sel, -1, n.Sel)
+
+ case *ast.IndexExpr:
+ walk(v, edge.IndexExpr_X, -1, n.X)
+ walk(v, edge.IndexExpr_Index, -1, n.Index)
+
+ case *ast.IndexListExpr:
+ walk(v, edge.IndexListExpr_X, -1, n.X)
+ walkList(v, edge.IndexListExpr_Indices, n.Indices)
+
+ case *ast.SliceExpr:
+ walk(v, edge.SliceExpr_X, -1, n.X)
+ if n.Low != nil {
+ walk(v, edge.SliceExpr_Low, -1, n.Low)
+ }
+ if n.High != nil {
+ walk(v, edge.SliceExpr_High, -1, n.High)
+ }
+ if n.Max != nil {
+ walk(v, edge.SliceExpr_Max, -1, n.Max)
+ }
+
+ case *ast.TypeAssertExpr:
+ walk(v, edge.TypeAssertExpr_X, -1, n.X)
+ if n.Type != nil {
+ walk(v, edge.TypeAssertExpr_Type, -1, n.Type)
+ }
+
+ case *ast.CallExpr:
+ walk(v, edge.CallExpr_Fun, -1, n.Fun)
+ walkList(v, edge.CallExpr_Args, n.Args)
+
+ case *ast.StarExpr:
+ walk(v, edge.StarExpr_X, -1, n.X)
+
+ case *ast.UnaryExpr:
+ walk(v, edge.UnaryExpr_X, -1, n.X)
+
+ case *ast.BinaryExpr:
+ walk(v, edge.BinaryExpr_X, -1, n.X)
+ walk(v, edge.BinaryExpr_Y, -1, n.Y)
+
+ case *ast.KeyValueExpr:
+ walk(v, edge.KeyValueExpr_Key, -1, n.Key)
+ walk(v, edge.KeyValueExpr_Value, -1, n.Value)
+
+ // Types
+ case *ast.ArrayType:
+ if n.Len != nil {
+ walk(v, edge.ArrayType_Len, -1, n.Len)
+ }
+ walk(v, edge.ArrayType_Elt, -1, n.Elt)
+
+ case *ast.StructType:
+ walk(v, edge.StructType_Fields, -1, n.Fields)
+
+ case *ast.FuncType:
+ if n.TypeParams != nil {
+ walk(v, edge.FuncType_TypeParams, -1, n.TypeParams)
+ }
+ if n.Params != nil {
+ walk(v, edge.FuncType_Params, -1, n.Params)
+ }
+ if n.Results != nil {
+ walk(v, edge.FuncType_Results, -1, n.Results)
+ }
+
+ case *ast.InterfaceType:
+ walk(v, edge.InterfaceType_Methods, -1, n.Methods)
+
+ case *ast.MapType:
+ walk(v, edge.MapType_Key, -1, n.Key)
+ walk(v, edge.MapType_Value, -1, n.Value)
+
+ case *ast.ChanType:
+ walk(v, edge.ChanType_Value, -1, n.Value)
+
+ // Statements
+ case *ast.BadStmt:
+ // nothing to do
+
+ case *ast.DeclStmt:
+ walk(v, edge.DeclStmt_Decl, -1, n.Decl)
+
+ case *ast.EmptyStmt:
+ // nothing to do
+
+ case *ast.LabeledStmt:
+ walk(v, edge.LabeledStmt_Label, -1, n.Label)
+ walk(v, edge.LabeledStmt_Stmt, -1, n.Stmt)
+
+ case *ast.ExprStmt:
+ walk(v, edge.ExprStmt_X, -1, n.X)
+
+ case *ast.SendStmt:
+ walk(v, edge.SendStmt_Chan, -1, n.Chan)
+ walk(v, edge.SendStmt_Value, -1, n.Value)
+
+ case *ast.IncDecStmt:
+ walk(v, edge.IncDecStmt_X, -1, n.X)
+
+ case *ast.AssignStmt:
+ walkList(v, edge.AssignStmt_Lhs, n.Lhs)
+ walkList(v, edge.AssignStmt_Rhs, n.Rhs)
+
+ case *ast.GoStmt:
+ walk(v, edge.GoStmt_Call, -1, n.Call)
+
+ case *ast.DeferStmt:
+ walk(v, edge.DeferStmt_Call, -1, n.Call)
+
+ case *ast.ReturnStmt:
+ walkList(v, edge.ReturnStmt_Results, n.Results)
+
+ case *ast.BranchStmt:
+ if n.Label != nil {
+ walk(v, edge.BranchStmt_Label, -1, n.Label)
+ }
+
+ case *ast.BlockStmt:
+ walkList(v, edge.BlockStmt_List, n.List)
+
+ case *ast.IfStmt:
+ if n.Init != nil {
+ walk(v, edge.IfStmt_Init, -1, n.Init)
+ }
+ walk(v, edge.IfStmt_Cond, -1, n.Cond)
+ walk(v, edge.IfStmt_Body, -1, n.Body)
+ if n.Else != nil {
+ walk(v, edge.IfStmt_Else, -1, n.Else)
+ }
+
+ case *ast.CaseClause:
+ walkList(v, edge.CaseClause_List, n.List)
+ walkList(v, edge.CaseClause_Body, n.Body)
+
+ case *ast.SwitchStmt:
+ if n.Init != nil {
+ walk(v, edge.SwitchStmt_Init, -1, n.Init)
+ }
+ if n.Tag != nil {
+ walk(v, edge.SwitchStmt_Tag, -1, n.Tag)
+ }
+ walk(v, edge.SwitchStmt_Body, -1, n.Body)
+
+ case *ast.TypeSwitchStmt:
+ if n.Init != nil {
+ walk(v, edge.TypeSwitchStmt_Init, -1, n.Init)
+ }
+ walk(v, edge.TypeSwitchStmt_Assign, -1, n.Assign)
+ walk(v, edge.TypeSwitchStmt_Body, -1, n.Body)
+
+ case *ast.CommClause:
+ if n.Comm != nil {
+ walk(v, edge.CommClause_Comm, -1, n.Comm)
+ }
+ walkList(v, edge.CommClause_Body, n.Body)
+
+ case *ast.SelectStmt:
+ walk(v, edge.SelectStmt_Body, -1, n.Body)
+
+ case *ast.ForStmt:
+ if n.Init != nil {
+ walk(v, edge.ForStmt_Init, -1, n.Init)
+ }
+ if n.Cond != nil {
+ walk(v, edge.ForStmt_Cond, -1, n.Cond)
+ }
+ if n.Post != nil {
+ walk(v, edge.ForStmt_Post, -1, n.Post)
+ }
+ walk(v, edge.ForStmt_Body, -1, n.Body)
+
+ case *ast.RangeStmt:
+ if n.Key != nil {
+ walk(v, edge.RangeStmt_Key, -1, n.Key)
+ }
+ if n.Value != nil {
+ walk(v, edge.RangeStmt_Value, -1, n.Value)
+ }
+ walk(v, edge.RangeStmt_X, -1, n.X)
+ walk(v, edge.RangeStmt_Body, -1, n.Body)
+
+ // Declarations
+ case *ast.ImportSpec:
+ if n.Doc != nil {
+ walk(v, edge.ImportSpec_Doc, -1, n.Doc)
+ }
+ if n.Name != nil {
+ walk(v, edge.ImportSpec_Name, -1, n.Name)
+ }
+ walk(v, edge.ImportSpec_Path, -1, n.Path)
+ if n.Comment != nil {
+ walk(v, edge.ImportSpec_Comment, -1, n.Comment)
+ }
+
+ case *ast.ValueSpec:
+ if n.Doc != nil {
+ walk(v, edge.ValueSpec_Doc, -1, n.Doc)
+ }
+ walkList(v, edge.ValueSpec_Names, n.Names)
+ if n.Type != nil {
+ walk(v, edge.ValueSpec_Type, -1, n.Type)
+ }
+ walkList(v, edge.ValueSpec_Values, n.Values)
+ if n.Comment != nil {
+ walk(v, edge.ValueSpec_Comment, -1, n.Comment)
+ }
+
+ case *ast.TypeSpec:
+ if n.Doc != nil {
+ walk(v, edge.TypeSpec_Doc, -1, n.Doc)
+ }
+ walk(v, edge.TypeSpec_Name, -1, n.Name)
+ if n.TypeParams != nil {
+ walk(v, edge.TypeSpec_TypeParams, -1, n.TypeParams)
+ }
+ walk(v, edge.TypeSpec_Type, -1, n.Type)
+ if n.Comment != nil {
+ walk(v, edge.TypeSpec_Comment, -1, n.Comment)
+ }
+
+ case *ast.BadDecl:
+ // nothing to do
+
+ case *ast.GenDecl:
+ if n.Doc != nil {
+ walk(v, edge.GenDecl_Doc, -1, n.Doc)
+ }
+ walkList(v, edge.GenDecl_Specs, n.Specs)
+
+ case *ast.FuncDecl:
+ if n.Doc != nil {
+ walk(v, edge.FuncDecl_Doc, -1, n.Doc)
+ }
+ if n.Recv != nil {
+ walk(v, edge.FuncDecl_Recv, -1, n.Recv)
+ }
+ walk(v, edge.FuncDecl_Name, -1, n.Name)
+ walk(v, edge.FuncDecl_Type, -1, n.Type)
+ if n.Body != nil {
+ walk(v, edge.FuncDecl_Body, -1, n.Body)
+ }
+
+ case *ast.File:
+ if n.Doc != nil {
+ walk(v, edge.File_Doc, -1, n.Doc)
+ }
+ walk(v, edge.File_Name, -1, n.Name)
+ walkList(v, edge.File_Decls, n.Decls)
+ // don't walk n.Comments - they have been
+ // visited already through the individual
+ // nodes
+
+ default:
+ // (includes *ast.Package)
+ panic(fmt.Sprintf("Walk: unexpected node type %T", n))
+ }
+
+ v.pop(node)
+}
diff --git a/vendor/golang.org/x/tools/go/packages/golist.go b/vendor/golang.org/x/tools/go/packages/golist.go
index 89f89dd2dc..680a70ca8f 100644
--- a/vendor/golang.org/x/tools/go/packages/golist.go
+++ b/vendor/golang.org/x/tools/go/packages/golist.go
@@ -364,12 +364,6 @@ type jsonPackage struct {
DepsErrors []*packagesinternal.PackageError
}
-type jsonPackageError struct {
- ImportStack []string
- Pos string
- Err string
-}
-
func otherFiles(p *jsonPackage) [][]string {
return [][]string{p.CFiles, p.CXXFiles, p.MFiles, p.HFiles, p.FFiles, p.SFiles, p.SwigFiles, p.SwigCXXFiles, p.SysoFiles}
}
diff --git a/vendor/golang.org/x/tools/go/packages/visit.go b/vendor/golang.org/x/tools/go/packages/visit.go
index df14ffd94d..af6a60d75f 100644
--- a/vendor/golang.org/x/tools/go/packages/visit.go
+++ b/vendor/golang.org/x/tools/go/packages/visit.go
@@ -5,9 +5,11 @@
package packages
import (
+ "cmp"
"fmt"
+ "iter"
"os"
- "sort"
+ "slices"
)
// Visit visits all the packages in the import graph whose roots are
@@ -16,6 +18,20 @@ import (
// package's dependencies have been visited (postorder).
// The boolean result of pre(pkg) determines whether
// the imports of package pkg are visited.
+//
+// Example:
+//
+// pkgs, err := Load(...)
+// if err != nil { ... }
+// Visit(pkgs, nil, func(pkg *Package) {
+// log.Println(pkg)
+// })
+//
+// In most cases, it is more convenient to use [Postorder]:
+//
+// for pkg := range Postorder(pkgs) {
+// log.Println(pkg)
+// }
func Visit(pkgs []*Package, pre func(*Package) bool, post func(*Package)) {
seen := make(map[*Package]bool)
var visit func(*Package)
@@ -24,13 +40,8 @@ func Visit(pkgs []*Package, pre func(*Package) bool, post func(*Package)) {
seen[pkg] = true
if pre == nil || pre(pkg) {
- paths := make([]string, 0, len(pkg.Imports))
- for path := range pkg.Imports {
- paths = append(paths, path)
- }
- sort.Strings(paths) // Imports is a map, this makes visit stable
- for _, path := range paths {
- visit(pkg.Imports[path])
+ for _, imp := range sorted(pkg.Imports) { // for determinism
+ visit(imp)
}
}
@@ -50,7 +61,7 @@ func Visit(pkgs []*Package, pre func(*Package) bool, post func(*Package)) {
func PrintErrors(pkgs []*Package) int {
var n int
errModules := make(map[*Module]bool)
- Visit(pkgs, nil, func(pkg *Package) {
+ for pkg := range Postorder(pkgs) {
for _, err := range pkg.Errors {
fmt.Fprintln(os.Stderr, err)
n++
@@ -63,6 +74,60 @@ func PrintErrors(pkgs []*Package) int {
fmt.Fprintln(os.Stderr, mod.Error.Err)
n++
}
- })
+ }
return n
}
+
+// Postorder returns an iterator over the the packages in
+// the import graph whose roots are pkg.
+// Packages are enumerated in dependencies-first order.
+func Postorder(pkgs []*Package) iter.Seq[*Package] {
+ return func(yield func(*Package) bool) {
+ seen := make(map[*Package]bool)
+ var visit func(*Package) bool
+ visit = func(pkg *Package) bool {
+ if !seen[pkg] {
+ seen[pkg] = true
+ for _, imp := range sorted(pkg.Imports) { // for determinism
+ if !visit(imp) {
+ return false
+ }
+ }
+ if !yield(pkg) {
+ return false
+ }
+ }
+ return true
+ }
+ for _, pkg := range pkgs {
+ if !visit(pkg) {
+ break
+ }
+ }
+ }
+}
+
+// -- copied from golang.org.x/tools/gopls/internal/util/moremaps --
+
+// sorted returns an iterator over the entries of m in key order.
+func sorted[M ~map[K]V, K cmp.Ordered, V any](m M) iter.Seq2[K, V] {
+ // TODO(adonovan): use maps.Sorted if proposal #68598 is accepted.
+ return func(yield func(K, V) bool) {
+ keys := keySlice(m)
+ slices.Sort(keys)
+ for _, k := range keys {
+ if !yield(k, m[k]) {
+ break
+ }
+ }
+ }
+}
+
+// KeySlice returns the keys of the map M, like slices.Collect(maps.Keys(m)).
+func keySlice[M ~map[K]V, K comparable, V any](m M) []K {
+ r := make([]K, 0, len(m))
+ for k := range m {
+ r = append(r, k)
+ }
+ return r
+}
diff --git a/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go b/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go
index d3c2913bef..6c0c74968f 100644
--- a/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go
+++ b/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go
@@ -698,7 +698,10 @@ func Object(pkg *types.Package, p Path) (types.Object, error) {
} else if false && aliases.Enabled() {
// The Enabled check is too expensive, so for now we
// simply assume that aliases are not enabled.
- // TODO(adonovan): replace with "if true {" when go1.24 is assured.
+ //
+ // Now that go1.24 is assured, we should be able to
+ // replace this with "if true {", but it causes tests
+ // to fail. TODO(adonovan): investigate.
return nil, fmt.Errorf("cannot apply %q to %s (got %T, want alias)", code, t, t)
}
diff --git a/vendor/golang.org/x/tools/go/types/typeutil/map.go b/vendor/golang.org/x/tools/go/types/typeutil/map.go
index b6d542c64e..f035a0b6be 100644
--- a/vendor/golang.org/x/tools/go/types/typeutil/map.go
+++ b/vendor/golang.org/x/tools/go/types/typeutil/map.go
@@ -11,7 +11,6 @@ import (
"fmt"
"go/types"
"hash/maphash"
- "unsafe"
"golang.org/x/tools/internal/typeparams"
)
@@ -380,22 +379,8 @@ var theSeed = maphash.MakeSeed()
func (hasher) hashTypeName(tname *types.TypeName) uint32 {
// Since types.Identical uses == to compare TypeNames,
// the Hash function uses maphash.Comparable.
- // TODO(adonovan): or will, when it becomes available in go1.24.
- // In the meantime we use the pointer's numeric value.
- //
- // hash := maphash.Comparable(theSeed, tname)
- //
- // (Another approach would be to hash the name and package
- // path, and whether or not it is a package-level typename. It
- // is rare for a package to define multiple local types with
- // the same name.)
- ptr := uintptr(unsafe.Pointer(tname))
- if unsafe.Sizeof(ptr) == 8 {
- hash := uint64(ptr)
- return uint32(hash ^ (hash >> 32))
- } else {
- return uint32(ptr)
- }
+ hash := maphash.Comparable(theSeed, tname)
+ return uint32(hash ^ (hash >> 32))
}
// shallowHash computes a hash of t without looking at any of its
diff --git a/vendor/golang.org/x/tools/imports/forward.go b/vendor/golang.org/x/tools/imports/forward.go
index cb6db8893f..22ae777726 100644
--- a/vendor/golang.org/x/tools/imports/forward.go
+++ b/vendor/golang.org/x/tools/imports/forward.go
@@ -69,9 +69,3 @@ func Process(filename string, src []byte, opt *Options) ([]byte, error) {
}
return intimp.Process(filename, src, intopt)
}
-
-// VendorlessPath returns the devendorized version of the import path ipath.
-// For example, VendorlessPath("foo/bar/vendor/a/b") returns "a/b".
-func VendorlessPath(ipath string) string {
- return intimp.VendorlessPath(ipath)
-}
diff --git a/vendor/golang.org/x/tools/internal/event/core/event.go b/vendor/golang.org/x/tools/internal/event/core/event.go
index a6cf0e64a4..ade5d1e799 100644
--- a/vendor/golang.org/x/tools/internal/event/core/event.go
+++ b/vendor/golang.org/x/tools/internal/event/core/event.go
@@ -28,11 +28,6 @@ type Event struct {
dynamic []label.Label // dynamically sized storage for remaining labels
}
-// eventLabelMap implements label.Map for a the labels of an Event.
-type eventLabelMap struct {
- event Event
-}
-
func (ev Event) At() time.Time { return ev.at }
func (ev Event) Format(f fmt.State, r rune) {
diff --git a/vendor/golang.org/x/tools/internal/gcimporter/iexport.go b/vendor/golang.org/x/tools/internal/gcimporter/iexport.go
index 780873e3ae..4a4357d2bd 100644
--- a/vendor/golang.org/x/tools/internal/gcimporter/iexport.go
+++ b/vendor/golang.org/x/tools/internal/gcimporter/iexport.go
@@ -569,7 +569,6 @@ func (p *iexporter) exportName(obj types.Object) (res string) {
type iexporter struct {
fset *token.FileSet
- out *bytes.Buffer
version int
shallow bool // don't put types from other packages in the index
diff --git a/vendor/golang.org/x/tools/internal/gcimporter/iimport_go122.go b/vendor/golang.org/x/tools/internal/gcimporter/iimport_go122.go
deleted file mode 100644
index 7586bfaca6..0000000000
--- a/vendor/golang.org/x/tools/internal/gcimporter/iimport_go122.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2024 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.22 && !go1.24
-
-package gcimporter
-
-import (
- "go/token"
- "go/types"
- "unsafe"
-)
-
-// TODO(rfindley): delete this workaround once go1.24 is assured.
-
-func init() {
- // Update markBlack so that it correctly sets the color
- // of imported TypeNames.
- //
- // See the doc comment for markBlack for details.
-
- type color uint32
- const (
- white color = iota
- black
- grey
- )
- type object struct {
- _ *types.Scope
- _ token.Pos
- _ *types.Package
- _ string
- _ types.Type
- _ uint32
- color_ color
- _ token.Pos
- }
- type typeName struct {
- object
- }
-
- // If the size of types.TypeName changes, this will fail to compile.
- const delta = int64(unsafe.Sizeof(typeName{})) - int64(unsafe.Sizeof(types.TypeName{}))
- var _ [-delta * delta]int
-
- markBlack = func(obj *types.TypeName) {
- type uP = unsafe.Pointer
- var ptr *typeName
- *(*uP)(uP(&ptr)) = uP(obj)
- ptr.color_ = black
- }
-}
diff --git a/vendor/golang.org/x/tools/internal/imports/fix.go b/vendor/golang.org/x/tools/internal/imports/fix.go
index 50b6ca51a6..1b4dc0cb5d 100644
--- a/vendor/golang.org/x/tools/internal/imports/fix.go
+++ b/vendor/golang.org/x/tools/internal/imports/fix.go
@@ -16,6 +16,7 @@ import (
"go/types"
"io/fs"
"io/ioutil"
+ "maps"
"os"
"path"
"path/filepath"
@@ -27,8 +28,6 @@ import (
"unicode"
"unicode/utf8"
- "maps"
-
"golang.org/x/tools/go/ast/astutil"
"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/gocommand"
@@ -43,7 +42,7 @@ var importToGroup = []func(localPrefix, importPath string) (num int, ok bool){
if localPrefix == "" {
return
}
- for _, p := range strings.Split(localPrefix, ",") {
+ for p := range strings.SplitSeq(localPrefix, ",") {
if strings.HasPrefix(importPath, p) || strings.TrimSuffix(p, "/") == importPath {
return 3, true
}
@@ -1251,7 +1250,6 @@ func ImportPathToAssumedName(importPath string) string {
// gopathResolver implements resolver for GOPATH workspaces.
type gopathResolver struct {
env *ProcessEnv
- walked bool
cache *DirInfoCache
scanSema chan struct{} // scanSema prevents concurrent scans.
}
diff --git a/vendor/golang.org/x/tools/internal/modindex/symbols.go b/vendor/golang.org/x/tools/internal/modindex/symbols.go
index fe24db9b13..8e9702d84b 100644
--- a/vendor/golang.org/x/tools/internal/modindex/symbols.go
+++ b/vendor/golang.org/x/tools/internal/modindex/symbols.go
@@ -206,8 +206,7 @@ func isDeprecated(doc *ast.CommentGroup) bool {
// go.dev/wiki/Deprecated Paragraph starting 'Deprecated:'
// This code fails for /* Deprecated: */, but it's the code from
// gopls/internal/analysis/deprecated
- lines := strings.Split(doc.Text(), "\n\n")
- for _, line := range lines {
+ for line := range strings.SplitSeq(doc.Text(), "\n\n") {
if strings.HasPrefix(line, "Deprecated:") {
return true
}
diff --git a/vendor/golang.org/x/tools/internal/stdlib/deps.go b/vendor/golang.org/x/tools/internal/stdlib/deps.go
index 77cf8d2181..96ad6c5821 100644
--- a/vendor/golang.org/x/tools/internal/stdlib/deps.go
+++ b/vendor/golang.org/x/tools/internal/stdlib/deps.go
@@ -12,348 +12,354 @@ type pkginfo struct {
}
var deps = [...]pkginfo{
- {"archive/tar", "\x03j\x03E5\x01\v\x01#\x01\x01\x02\x05\n\x02\x01\x02\x02\v"},
- {"archive/zip", "\x02\x04`\a\x16\x0205\x01+\x05\x01\x11\x03\x02\r\x04"},
- {"bufio", "\x03j}F\x13"},
- {"bytes", "m+R\x03\fH\x02\x02"},
+ {"archive/tar", "\x03k\x03E;\x01\n\x01$\x01\x01\x02\x05\b\x02\x01\x02\x02\f"},
+ {"archive/zip", "\x02\x04a\a\x03\x12\x021;\x01+\x05\x01\x0f\x03\x02\x0e\x04"},
+ {"bufio", "\x03k\x83\x01D\x14"},
+ {"bytes", "n*Y\x03\fG\x02\x02"},
{"cmp", ""},
- {"compress/bzip2", "\x02\x02\xe6\x01C"},
- {"compress/flate", "\x02k\x03z\r\x025\x01\x03"},
- {"compress/gzip", "\x02\x04`\a\x03\x15eU"},
- {"compress/lzw", "\x02k\x03z"},
- {"compress/zlib", "\x02\x04`\a\x03\x13\x01f"},
- {"container/heap", "\xae\x02"},
+ {"compress/bzip2", "\x02\x02\xed\x01A"},
+ {"compress/flate", "\x02l\x03\x80\x01\f\x033\x01\x03"},
+ {"compress/gzip", "\x02\x04a\a\x03\x14lT"},
+ {"compress/lzw", "\x02l\x03\x80\x01"},
+ {"compress/zlib", "\x02\x04a\a\x03\x12\x01m"},
+ {"container/heap", "\xb3\x02"},
{"container/list", ""},
{"container/ring", ""},
- {"context", "m\\i\x01\f"},
- {"crypto", "\x83\x01gE"},
- {"crypto/aes", "\x10\n\a\x8e\x02"},
- {"crypto/cipher", "\x03\x1e\x01\x01\x1d\x11\x1c,Q"},
- {"crypto/des", "\x10\x13\x1d-,\x96\x01\x03"},
- {"crypto/dsa", "@\x04)}\x0e"},
- {"crypto/ecdh", "\x03\v\f\x0e\x04\x14\x04\r\x1c}"},
- {"crypto/ecdsa", "\x0e\x05\x03\x04\x01\x0e\x16\x01\x04\f\x01\x1c}\x0e\x04L\x01"},
- {"crypto/ed25519", "\x0e\x1c\x16\n\a\x1c}E"},
- {"crypto/elliptic", "0=}\x0e:"},
- {"crypto/fips140", " \x05\x90\x01"},
- {"crypto/hkdf", "-\x12\x01-\x16"},
- {"crypto/hmac", "\x1a\x14\x11\x01\x112"},
+ {"context", "n\\m\x01\r"},
+ {"crypto", "\x83\x01nC"},
+ {"crypto/aes", "\x10\n\a\x93\x02"},
+ {"crypto/cipher", "\x03\x1e\x01\x01\x1e\x11\x1c+X"},
+ {"crypto/des", "\x10\x13\x1e-+\x9b\x01\x03"},
+ {"crypto/dsa", "A\x04)\x83\x01\r"},
+ {"crypto/ecdh", "\x03\v\f\x0e\x04\x15\x04\r\x1c\x83\x01"},
+ {"crypto/ecdsa", "\x0e\x05\x03\x04\x01\x0e\a\v\x05\x01\x04\f\x01\x1c\x83\x01\r\x05K\x01"},
+ {"crypto/ed25519", "\x0e\x1c\x11\x06\n\a\x1c\x83\x01C"},
+ {"crypto/elliptic", "0>\x83\x01\r9"},
+ {"crypto/fips140", " \x05"},
+ {"crypto/hkdf", "-\x13\x01-\x15"},
+ {"crypto/hmac", "\x1a\x14\x12\x01\x111"},
{"crypto/internal/boring", "\x0e\x02\rf"},
- {"crypto/internal/boring/bbig", "\x1a\xde\x01M"},
- {"crypto/internal/boring/bcache", "\xb3\x02\x12"},
+ {"crypto/internal/boring/bbig", "\x1a\xe4\x01M"},
+ {"crypto/internal/boring/bcache", "\xb8\x02\x13"},
{"crypto/internal/boring/sig", ""},
- {"crypto/internal/cryptotest", "\x03\r\n)\x0e\x19\x06\x13\x12#\a\t\x11\x11\x11\x1b\x01\f\r\x05\n"},
- {"crypto/internal/entropy", "E"},
- {"crypto/internal/fips140", ">/}9\r\x15"},
- {"crypto/internal/fips140/aes", "\x03\x1d\x03\x02\x13\x04\x01\x01\x05*\x8c\x016"},
- {"crypto/internal/fips140/aes/gcm", " \x01\x02\x02\x02\x11\x04\x01\x06*\x8a\x01"},
- {"crypto/internal/fips140/alias", "\xc5\x02"},
- {"crypto/internal/fips140/bigmod", "%\x17\x01\x06*\x8c\x01"},
- {"crypto/internal/fips140/check", " \x0e\x06\b\x02\xac\x01["},
- {"crypto/internal/fips140/check/checktest", "%\xfe\x01\""},
- {"crypto/internal/fips140/drbg", "\x03\x1c\x01\x01\x04\x13\x04\b\x01(}\x0f9"},
- {"crypto/internal/fips140/ecdh", "\x03\x1d\x05\x02\t\f1}\x0f9"},
- {"crypto/internal/fips140/ecdsa", "\x03\x1d\x04\x01\x02\a\x02\x067}H"},
- {"crypto/internal/fips140/ed25519", "\x03\x1d\x05\x02\x04\v7\xc2\x01\x03"},
- {"crypto/internal/fips140/edwards25519", "%\a\f\x041\x8c\x019"},
- {"crypto/internal/fips140/edwards25519/field", "%\x13\x041\x8c\x01"},
- {"crypto/internal/fips140/hkdf", "\x03\x1d\x05\t\x069"},
- {"crypto/internal/fips140/hmac", "\x03\x1d\x14\x01\x017"},
- {"crypto/internal/fips140/mlkem", "\x03\x1d\x05\x02\x0e\x03\x041"},
- {"crypto/internal/fips140/nistec", "%\f\a\x041\x8c\x01*\x0f\x13"},
- {"crypto/internal/fips140/nistec/fiat", "%\x135\x8c\x01"},
- {"crypto/internal/fips140/pbkdf2", "\x03\x1d\x05\t\x069"},
- {"crypto/internal/fips140/rsa", "\x03\x1d\x04\x01\x02\r\x01\x01\x025}H"},
- {"crypto/internal/fips140/sha256", "\x03\x1d\x1c\x01\x06*\x8c\x01"},
- {"crypto/internal/fips140/sha3", "\x03\x1d\x18\x04\x010\x8c\x01L"},
- {"crypto/internal/fips140/sha512", "\x03\x1d\x1c\x01\x06*\x8c\x01"},
- {"crypto/internal/fips140/ssh", " \x05"},
- {"crypto/internal/fips140/subtle", "#"},
- {"crypto/internal/fips140/tls12", "\x03\x1d\x05\t\x06\x027"},
- {"crypto/internal/fips140/tls13", "\x03\x1d\x05\b\a\b1"},
+ {"crypto/internal/cryptotest", "\x03\r\n\x06$\x0e\x19\x06\x12\x12 \x04\a\t\x16\x01\x11\x11\x1b\x01\a\x05\b\x03\x05\v"},
+ {"crypto/internal/entropy", "F"},
+ {"crypto/internal/fips140", "?/\x15\xa7\x01\v\x16"},
+ {"crypto/internal/fips140/aes", "\x03\x1d\x03\x02\x13\x05\x01\x01\x05*\x92\x014"},
+ {"crypto/internal/fips140/aes/gcm", " \x01\x02\x02\x02\x11\x05\x01\x06*\x8f\x01"},
+ {"crypto/internal/fips140/alias", "\xcb\x02"},
+ {"crypto/internal/fips140/bigmod", "%\x18\x01\x06*\x92\x01"},
+ {"crypto/internal/fips140/check", " \x0e\x06\t\x02\xb2\x01Z"},
+ {"crypto/internal/fips140/check/checktest", "%\x85\x02!"},
+ {"crypto/internal/fips140/drbg", "\x03\x1c\x01\x01\x04\x13\x05\b\x01(\x83\x01\x0f7"},
+ {"crypto/internal/fips140/ecdh", "\x03\x1d\x05\x02\t\r1\x83\x01\x0f7"},
+ {"crypto/internal/fips140/ecdsa", "\x03\x1d\x04\x01\x02\a\x02\x068\x15nF"},
+ {"crypto/internal/fips140/ed25519", "\x03\x1d\x05\x02\x04\v8\xc6\x01\x03"},
+ {"crypto/internal/fips140/edwards25519", "%\a\f\x051\x92\x017"},
+ {"crypto/internal/fips140/edwards25519/field", "%\x13\x051\x92\x01"},
+ {"crypto/internal/fips140/hkdf", "\x03\x1d\x05\t\x06:\x15"},
+ {"crypto/internal/fips140/hmac", "\x03\x1d\x14\x01\x018\x15"},
+ {"crypto/internal/fips140/mlkem", "\x03\x1d\x05\x02\x0e\x03\x051"},
+ {"crypto/internal/fips140/nistec", "%\f\a\x051\x92\x01*\r\x14"},
+ {"crypto/internal/fips140/nistec/fiat", "%\x136\x92\x01"},
+ {"crypto/internal/fips140/pbkdf2", "\x03\x1d\x05\t\x06:\x15"},
+ {"crypto/internal/fips140/rsa", "\x03\x1d\x04\x01\x02\r\x01\x01\x026\x15nF"},
+ {"crypto/internal/fips140/sha256", "\x03\x1d\x1d\x01\x06*\x15}"},
+ {"crypto/internal/fips140/sha3", "\x03\x1d\x18\x05\x010\x92\x01K"},
+ {"crypto/internal/fips140/sha512", "\x03\x1d\x1d\x01\x06*\x15}"},
+ {"crypto/internal/fips140/ssh", "%^"},
+ {"crypto/internal/fips140/subtle", "#\x1a\xc3\x01"},
+ {"crypto/internal/fips140/tls12", "\x03\x1d\x05\t\x06\x028\x15"},
+ {"crypto/internal/fips140/tls13", "\x03\x1d\x05\b\a\t1\x15"},
+ {"crypto/internal/fips140cache", "\xaa\x02\r&"},
{"crypto/internal/fips140deps", ""},
{"crypto/internal/fips140deps/byteorder", "\x99\x01"},
- {"crypto/internal/fips140deps/cpu", "\xad\x01\a"},
- {"crypto/internal/fips140deps/godebug", "\xb5\x01"},
- {"crypto/internal/fips140hash", "5\x1a4\xc2\x01"},
- {"crypto/internal/fips140only", "'\r\x01\x01M25"},
+ {"crypto/internal/fips140deps/cpu", "\xae\x01\a"},
+ {"crypto/internal/fips140deps/godebug", "\xb6\x01"},
+ {"crypto/internal/fips140hash", "5\x1b3\xc8\x01"},
+ {"crypto/internal/fips140only", "'\r\x01\x01M3;"},
{"crypto/internal/fips140test", ""},
- {"crypto/internal/hpke", "\x0e\x01\x01\x03\x1a\x1d#,`N"},
- {"crypto/internal/impl", "\xb0\x02"},
- {"crypto/internal/randutil", "\xea\x01\x12"},
- {"crypto/internal/sysrand", "mi!\x1f\r\x0f\x01\x01\v\x06"},
- {"crypto/internal/sysrand/internal/seccomp", "m"},
- {"crypto/md5", "\x0e2-\x16\x16`"},
+ {"crypto/internal/hpke", "\x0e\x01\x01\x03\x053#+gM"},
+ {"crypto/internal/impl", "\xb5\x02"},
+ {"crypto/internal/randutil", "\xf1\x01\x12"},
+ {"crypto/internal/sysrand", "nn! \r\r\x01\x01\f\x06"},
+ {"crypto/internal/sysrand/internal/seccomp", "n"},
+ {"crypto/md5", "\x0e3-\x15\x16g"},
{"crypto/mlkem", "/"},
- {"crypto/pbkdf2", "2\r\x01-\x16"},
- {"crypto/rand", "\x1a\x06\a\x19\x04\x01(}\x0eM"},
- {"crypto/rc4", "#\x1d-\xc2\x01"},
- {"crypto/rsa", "\x0e\f\x01\t\x0f\f\x01\x04\x06\a\x1c\x03\x1325\r\x01"},
- {"crypto/sha1", "\x0e\f&-\x16\x16\x14L"},
+ {"crypto/pbkdf2", "2\x0e\x01-\x15"},
+ {"crypto/rand", "\x1a\x06\a\x1a\x04\x01(\x83\x01\rM"},
+ {"crypto/rc4", "#\x1e-\xc6\x01"},
+ {"crypto/rsa", "\x0e\f\x01\t\x0f\r\x01\x04\x06\a\x1c\x03\x123;\f\x01"},
+ {"crypto/sha1", "\x0e\f'\x03*\x15\x16\x15R"},
{"crypto/sha256", "\x0e\f\x1aO"},
- {"crypto/sha3", "\x0e'N\xc2\x01"},
+ {"crypto/sha3", "\x0e'N\xc8\x01"},
{"crypto/sha512", "\x0e\f\x1cM"},
- {"crypto/subtle", "8\x96\x01U"},
- {"crypto/tls", "\x03\b\x02\x01\x01\x01\x01\x02\x01\x01\x01\x03\x01\a\x01\v\x02\n\x01\b\x05\x03\x01\x01\x01\x01\x02\x01\x02\x01\x17\x02\x03\x13\x16\x14\b5\x16\x16\r\n\x01\x01\x01\x02\x01\f\x06\x02\x01"},
- {"crypto/tls/internal/fips140tls", " \x93\x02"},
- {"crypto/x509", "\x03\v\x01\x01\x01\x01\x01\x01\x01\x011\x03\x02\x01\x01\x02\x05\x0e\x06\x02\x02\x03E\x032\x01\x02\t\x01\x01\x01\a\x10\x05\x01\x06\x02\x05\f\x01\x02\r\x02\x01\x01\x02\x03\x01"},
- {"crypto/x509/pkix", "c\x06\a\x88\x01G"},
- {"database/sql", "\x03\nJ\x16\x03z\f\x06\"\x05\n\x02\x03\x01\f\x02\x02\x02"},
- {"database/sql/driver", "\r`\x03\xae\x01\x11\x10"},
- {"debug/buildinfo", "\x03W\x02\x01\x01\b\a\x03`\x18\x02\x01+\x0f "},
- {"debug/dwarf", "\x03c\a\x03z1\x13\x01\x01"},
- {"debug/elf", "\x03\x06P\r\a\x03`\x19\x01,\x19\x01\x15"},
- {"debug/gosym", "\x03c\n\xbe\x01\x01\x01\x02"},
- {"debug/macho", "\x03\x06P\r\n`\x1a,\x19\x01"},
- {"debug/pe", "\x03\x06P\r\a\x03`\x1a,\x19\x01\x15"},
- {"debug/plan9obj", "f\a\x03`\x1a,"},
- {"embed", "m+:\x18\x01T"},
+ {"crypto/subtle", "8\x9b\x01W"},
+ {"crypto/tls", "\x03\b\x02\x01\x01\x01\x01\x02\x01\x01\x01\x02\x01\x01\a\x01\r\n\x01\t\x05\x03\x01\x01\x01\x01\x02\x01\x02\x01\x17\x02\x03\x12\x16\x15\b;\x16\x16\r\b\x01\x01\x01\x02\x01\r\x06\x02\x01\x0f"},
+ {"crypto/tls/internal/fips140tls", "\x17\xa1\x02"},
+ {"crypto/x509", "\x03\v\x01\x01\x01\x01\x01\x01\x01\x012\x05\x01\x01\x02\x05\x0e\x06\x02\x02\x03E\x038\x01\x02\b\x01\x01\x02\a\x10\x05\x01\x06\x02\x05\n\x01\x02\x0e\x02\x01\x01\x02\x03\x01"},
+ {"crypto/x509/pkix", "d\x06\a\x8d\x01G"},
+ {"database/sql", "\x03\nK\x16\x03\x80\x01\v\a\"\x05\b\x02\x03\x01\r\x02\x02\x02"},
+ {"database/sql/driver", "\ra\x03\xb4\x01\x0f\x11"},
+ {"debug/buildinfo", "\x03X\x02\x01\x01\b\a\x03e\x19\x02\x01+\x0f\x1f"},
+ {"debug/dwarf", "\x03d\a\x03\x80\x011\x11\x01\x01"},
+ {"debug/elf", "\x03\x06Q\r\a\x03e\x1a\x01,\x17\x01\x16"},
+ {"debug/gosym", "\x03d\n\xc2\x01\x01\x01\x02"},
+ {"debug/macho", "\x03\x06Q\r\ne\x1b,\x17\x01"},
+ {"debug/pe", "\x03\x06Q\r\a\x03e\x1b,\x17\x01\x16"},
+ {"debug/plan9obj", "g\a\x03e\x1b,"},
+ {"embed", "n*@\x19\x01S"},
{"embed/internal/embedtest", ""},
{"encoding", ""},
- {"encoding/ascii85", "\xea\x01E"},
- {"encoding/asn1", "\x03j\x03\x87\x01\x01&\x0f\x02\x01\x0f\x03\x01"},
- {"encoding/base32", "\xea\x01C\x02"},
- {"encoding/base64", "\x99\x01QC\x02"},
- {"encoding/binary", "m}\r'\x0f\x05"},
- {"encoding/csv", "\x02\x01j\x03zF\x11\x02"},
- {"encoding/gob", "\x02_\x05\a\x03`\x1a\f\x01\x02\x1d\b\x14\x01\x0e\x02"},
- {"encoding/hex", "m\x03zC\x03"},
- {"encoding/json", "\x03\x01]\x04\b\x03z\r'\x0f\x02\x01\x02\x0f\x01\x01\x02"},
- {"encoding/pem", "\x03b\b}C\x03"},
- {"encoding/xml", "\x02\x01^\f\x03z4\x05\f\x01\x02\x0f\x02"},
- {"errors", "\xc9\x01|"},
- {"expvar", "jK9\t\n\x15\r\n\x02\x03\x01\x10"},
- {"flag", "a\f\x03z,\b\x05\n\x02\x01\x0f"},
- {"fmt", "mE8\r\x1f\b\x0f\x02\x03\x11"},
- {"go/ast", "\x03\x01l\x0f\x01j\x03)\b\x0f\x02\x01"},
- {"go/ast/internal/tests", ""},
- {"go/build", "\x02\x01j\x03\x01\x03\x02\a\x02\x01\x17\x1e\x04\x02\t\x14\x12\x01+\x01\x04\x01\a\n\x02\x01\x11\x02\x02"},
- {"go/build/constraint", "m\xc2\x01\x01\x11\x02"},
- {"go/constant", "p\x10w\x01\x016\x01\x02\x11"},
- {"go/doc", "\x04l\x01\x06\t=-1\x12\x02\x01\x11\x02"},
- {"go/doc/comment", "\x03m\xbd\x01\x01\x01\x01\x11\x02"},
- {"go/format", "\x03m\x01\f\x01\x02jF"},
- {"go/importer", "s\a\x01\x01\x04\x01i9"},
- {"go/internal/gccgoimporter", "\x02\x01W\x13\x03\x05\v\x01g\x02,\x01\x05\x13\x01\v\b"},
- {"go/internal/gcimporter", "\x02n\x10\x01/\x05\x0e',\x17\x03\x02"},
- {"go/internal/srcimporter", "p\x01\x02\n\x03\x01i,\x01\x05\x14\x02\x13"},
- {"go/parser", "\x03j\x03\x01\x03\v\x01j\x01+\x06\x14"},
- {"go/printer", "p\x01\x03\x03\tj\r\x1f\x17\x02\x01\x02\n\x05\x02"},
- {"go/scanner", "\x03m\x10j2\x12\x01\x12\x02"},
- {"go/token", "\x04l\xbd\x01\x02\x03\x01\x0e\x02"},
- {"go/types", "\x03\x01\x06c\x03\x01\x04\b\x03\x02\x15\x1e\x06+\x04\x03\n%\a\n\x01\x01\x01\x02\x01\x0e\x02\x02"},
- {"go/version", "\xba\x01v"},
- {"hash", "\xea\x01"},
- {"hash/adler32", "m\x16\x16"},
- {"hash/crc32", "m\x16\x16\x14\x85\x01\x01\x12"},
- {"hash/crc64", "m\x16\x16\x99\x01"},
- {"hash/fnv", "m\x16\x16`"},
- {"hash/maphash", "\x94\x01\x05\x1b\x03@N"},
- {"html", "\xb0\x02\x02\x11"},
- {"html/template", "\x03g\x06\x19,5\x01\v \x05\x01\x02\x03\x0e\x01\x02\v\x01\x03\x02"},
- {"image", "\x02k\x1f^\x0f6\x03\x01"},
+ {"encoding/ascii85", "\xf1\x01C"},
+ {"encoding/asn1", "\x03k\x03\x8c\x01\x01'\r\x02\x01\x10\x03\x01"},
+ {"encoding/base32", "\xf1\x01A\x02"},
+ {"encoding/base64", "\x99\x01XA\x02"},
+ {"encoding/binary", "n\x83\x01\f(\r\x05"},
+ {"encoding/csv", "\x02\x01k\x03\x80\x01D\x12\x02"},
+ {"encoding/gob", "\x02`\x05\a\x03e\x1b\v\x01\x03\x1d\b\x12\x01\x0f\x02"},
+ {"encoding/hex", "n\x03\x80\x01A\x03"},
+ {"encoding/json", "\x03\x01^\x04\b\x03\x80\x01\f(\r\x02\x01\x02\x10\x01\x01\x02"},
+ {"encoding/pem", "\x03c\b\x83\x01A\x03"},
+ {"encoding/xml", "\x02\x01_\f\x03\x80\x014\x05\n\x01\x02\x10\x02"},
+ {"errors", "\xca\x01\x81\x01"},
+ {"expvar", "kK?\b\v\x15\r\b\x02\x03\x01\x11"},
+ {"flag", "b\f\x03\x80\x01,\b\x05\b\x02\x01\x10"},
+ {"fmt", "nE>\f \b\r\x02\x03\x12"},
+ {"go/ast", "\x03\x01m\x0e\x01q\x03)\b\r\x02\x01"},
+ {"go/build", "\x02\x01k\x03\x01\x02\x02\a\x02\x01\x17\x1f\x04\x02\t\x19\x13\x01+\x01\x04\x01\a\b\x02\x01\x12\x02\x02"},
+ {"go/build/constraint", "n\xc6\x01\x01\x12\x02"},
+ {"go/constant", "q\x0f}\x01\x024\x01\x02\x12"},
+ {"go/doc", "\x04m\x01\x05\t>31\x10\x02\x01\x12\x02"},
+ {"go/doc/comment", "\x03n\xc1\x01\x01\x01\x01\x12\x02"},
+ {"go/format", "\x03n\x01\v\x01\x02qD"},
+ {"go/importer", "s\a\x01\x01\x04\x01p9"},
+ {"go/internal/gccgoimporter", "\x02\x01X\x13\x03\x04\v\x01n\x02,\x01\x05\x11\x01\f\b"},
+ {"go/internal/gcimporter", "\x02o\x0f\x010\x05\x0e-,\x15\x03\x02"},
+ {"go/internal/srcimporter", "q\x01\x01\n\x03\x01p,\x01\x05\x12\x02\x14"},
+ {"go/parser", "\x03k\x03\x01\x02\v\x01q\x01+\x06\x12"},
+ {"go/printer", "q\x01\x02\x03\tq\f \x15\x02\x01\x02\v\x05\x02"},
+ {"go/scanner", "\x03n\x0fq2\x10\x01\x13\x02"},
+ {"go/token", "\x04m\x83\x01>\x02\x03\x01\x0f\x02"},
+ {"go/types", "\x03\x01\x06d\x03\x01\x03\b\x03\x02\x15\x1f\x061\x04\x03\t \x06\a\b\x01\x01\x01\x02\x01\x0f\x02\x02"},
+ {"go/version", "\xbb\x01z"},
+ {"hash", "\xf1\x01"},
+ {"hash/adler32", "n\x15\x16"},
+ {"hash/crc32", "n\x15\x16\x15\x89\x01\x01\x13"},
+ {"hash/crc64", "n\x15\x16\x9e\x01"},
+ {"hash/fnv", "n\x15\x16g"},
+ {"hash/maphash", "\x83\x01\x11!\x03\x93\x01"},
+ {"html", "\xb5\x02\x02\x12"},
+ {"html/template", "\x03h\x06\x18-;\x01\n!\x05\x01\x02\x03\f\x01\x02\f\x01\x03\x02"},
+ {"image", "\x02l\x1ee\x0f4\x03\x01"},
{"image/color", ""},
{"image/color/palette", "\x8c\x01"},
{"image/draw", "\x8b\x01\x01\x04"},
- {"image/gif", "\x02\x01\x05e\x03\x1b\x01\x01\x01\vQ"},
+ {"image/gif", "\x02\x01\x05f\x03\x1a\x01\x01\x01\vX"},
{"image/internal/imageutil", "\x8b\x01"},
- {"image/jpeg", "\x02k\x1e\x01\x04Z"},
- {"image/png", "\x02\a]\n\x13\x02\x06\x01^E"},
- {"index/suffixarray", "\x03c\a}\r*\f\x01"},
- {"internal/abi", "\xb4\x01\x91\x01"},
- {"internal/asan", "\xc5\x02"},
- {"internal/bisect", "\xa3\x02\x0f\x01"},
- {"internal/buildcfg", "pG_\x06\x02\x05\f\x01"},
- {"internal/bytealg", "\xad\x01\x98\x01"},
+ {"image/jpeg", "\x02l\x1d\x01\x04a"},
+ {"image/png", "\x02\a^\n\x12\x02\x06\x01eC"},
+ {"index/suffixarray", "\x03d\a\x83\x01\f+\n\x01"},
+ {"internal/abi", "\xb5\x01\x96\x01"},
+ {"internal/asan", "\xcb\x02"},
+ {"internal/bisect", "\xaa\x02\r\x01"},
+ {"internal/buildcfg", "qGe\x06\x02\x05\n\x01"},
+ {"internal/bytealg", "\xae\x01\x9d\x01"},
{"internal/byteorder", ""},
{"internal/cfg", ""},
- {"internal/chacha8rand", "\x99\x01\x1b\x91\x01"},
+ {"internal/cgrouptest", "q[Q\x06\x0f\x02\x01\x04\x01"},
+ {"internal/chacha8rand", "\x99\x01\x15\a\x96\x01"},
{"internal/copyright", ""},
{"internal/coverage", ""},
{"internal/coverage/calloc", ""},
- {"internal/coverage/cfile", "j\x06\x17\x16\x01\x02\x01\x01\x01\x01\x01\x01\x01#\x01\x1f,\x06\a\f\x01\x03\f\x06"},
- {"internal/coverage/cformat", "\x04l-\x04I\f7\x01\x02\f"},
- {"internal/coverage/cmerge", "p-Z"},
- {"internal/coverage/decodecounter", "f\n-\v\x02@,\x19\x16"},
- {"internal/coverage/decodemeta", "\x02d\n\x17\x16\v\x02@,"},
- {"internal/coverage/encodecounter", "\x02d\n-\f\x01\x02>\f \x17"},
- {"internal/coverage/encodemeta", "\x02\x01c\n\x13\x04\x16\r\x02>,/"},
- {"internal/coverage/pods", "\x04l-y\x06\x05\f\x02\x01"},
- {"internal/coverage/rtcov", "\xc5\x02"},
- {"internal/coverage/slicereader", "f\nz["},
- {"internal/coverage/slicewriter", "pz"},
- {"internal/coverage/stringtab", "p8\x04>"},
+ {"internal/coverage/cfile", "k\x06\x16\x17\x01\x02\x01\x01\x01\x01\x01\x01\x01#\x02$,\x06\a\n\x01\x03\r\x06"},
+ {"internal/coverage/cformat", "\x04m-\x04O\v6\x01\x02\r"},
+ {"internal/coverage/cmerge", "q-_"},
+ {"internal/coverage/decodecounter", "g\n-\v\x02F,\x17\x17"},
+ {"internal/coverage/decodemeta", "\x02e\n\x16\x17\v\x02F,"},
+ {"internal/coverage/encodecounter", "\x02e\n-\f\x01\x02D\v!\x15"},
+ {"internal/coverage/encodemeta", "\x02\x01d\n\x12\x04\x17\r\x02D,."},
+ {"internal/coverage/pods", "\x04m-\x7f\x06\x05\n\x02\x01"},
+ {"internal/coverage/rtcov", "\xcb\x02"},
+ {"internal/coverage/slicereader", "g\n\x80\x01Z"},
+ {"internal/coverage/slicewriter", "q\x80\x01"},
+ {"internal/coverage/stringtab", "q8\x04D"},
{"internal/coverage/test", ""},
{"internal/coverage/uleb128", ""},
- {"internal/cpu", "\xc5\x02"},
- {"internal/dag", "\x04l\xbd\x01\x03"},
- {"internal/diff", "\x03m\xbe\x01\x02"},
- {"internal/exportdata", "\x02\x01j\x03\x03]\x1a,\x01\x05\x13\x01\x02"},
- {"internal/filepathlite", "m+:\x19B"},
- {"internal/fmtsort", "\x04\x9a\x02\x0f"},
- {"internal/fuzz", "\x03\nA\x18\x04\x03\x03\x01\f\x0355\r\x02\x1d\x01\x05\x02\x05\f\x01\x02\x01\x01\v\x04\x02"},
+ {"internal/cpu", "\xcb\x02"},
+ {"internal/dag", "\x04m\xc1\x01\x03"},
+ {"internal/diff", "\x03n\xc2\x01\x02"},
+ {"internal/exportdata", "\x02\x01k\x03\x02c\x1b,\x01\x05\x11\x01\x02"},
+ {"internal/filepathlite", "n*@\x1a@"},
+ {"internal/fmtsort", "\x04\xa1\x02\r"},
+ {"internal/fuzz", "\x03\nB\x18\x04\x03\x03\x01\v\x036;\f\x03\x1d\x01\x05\x02\x05\n\x01\x02\x01\x01\f\x04\x02"},
{"internal/goarch", ""},
- {"internal/godebug", "\x96\x01 |\x01\x12"},
+ {"internal/godebug", "\x96\x01!\x80\x01\x01\x13"},
{"internal/godebugs", ""},
{"internal/goexperiment", ""},
{"internal/goos", ""},
- {"internal/goroot", "\x96\x02\x01\x05\x14\x02"},
+ {"internal/goroot", "\x9d\x02\x01\x05\x12\x02"},
{"internal/gover", "\x04"},
{"internal/goversion", ""},
{"internal/itoa", ""},
- {"internal/lazyregexp", "\x96\x02\v\x0f\x02"},
- {"internal/lazytemplate", "\xea\x01,\x1a\x02\v"},
- {"internal/msan", "\xc5\x02"},
+ {"internal/lazyregexp", "\x9d\x02\v\r\x02"},
+ {"internal/lazytemplate", "\xf1\x01,\x18\x02\f"},
+ {"internal/msan", "\xcb\x02"},
{"internal/nettrace", ""},
- {"internal/obscuretestdata", "e\x85\x01,"},
- {"internal/oserror", "m"},
- {"internal/pkgbits", "\x03K\x18\a\x03\x05\vj\x0e\x1e\r\f\x01"},
+ {"internal/obscuretestdata", "f\x8b\x01,"},
+ {"internal/oserror", "n"},
+ {"internal/pkgbits", "\x03L\x18\a\x03\x04\vq\r\x1f\r\n\x01"},
{"internal/platform", ""},
- {"internal/poll", "mO\x1a\x149\x0f\x01\x01\v\x06"},
- {"internal/profile", "\x03\x04f\x03z7\r\x01\x01\x0f"},
+ {"internal/poll", "nO\x1f\x159\r\x01\x01\f\x06"},
+ {"internal/profile", "\x03\x04g\x03\x80\x017\v\x01\x01\x10"},
{"internal/profilerecord", ""},
- {"internal/race", "\x94\x01\xb1\x01"},
- {"internal/reflectlite", "\x94\x01 3<\""},
- {"internal/runtime/atomic", "\xc5\x02"},
- {"internal/runtime/exithook", "\xca\x01{"},
- {"internal/runtime/maps", "\x94\x01\x01\x1f\v\t\x05\x01w"},
- {"internal/runtime/math", "\xb4\x01"},
- {"internal/runtime/sys", "\xb4\x01\x04"},
- {"internal/runtime/syscall", "\xc5\x02"},
- {"internal/saferio", "\xea\x01["},
- {"internal/singleflight", "\xb2\x02"},
- {"internal/stringslite", "\x98\x01\xad\x01"},
- {"internal/sync", "\x94\x01 \x14k\x12"},
- {"internal/synctest", "\xc5\x02"},
- {"internal/syscall/execenv", "\xb4\x02"},
- {"internal/syscall/unix", "\xa3\x02\x10\x01\x11"},
- {"internal/sysinfo", "\x02\x01\xaa\x01=,\x1a\x02"},
+ {"internal/race", "\x94\x01\xb7\x01"},
+ {"internal/reflectlite", "\x94\x01!9\b\x13\x01\a\x03E;\x01\x03\a\x01\x03\x02\x02\x01\x02\x06\x02\x01\x01\n\x01\x01\x05\x01\x02\x05\b\x01\x01\x01\x02\x01\r\x02\x02\x02\b\x01\x01\x01"},
+ {"net/http/cgi", "\x02Q\x1b\x03\x80\x01\x04\a\v\x01\x13\x01\x01\x01\x04\x01\x05\x02\b\x02\x01\x10\x0e"},
+ {"net/http/cookiejar", "\x04j\x03\x96\x01\x01\b\f\x16\x03\x02\x0e\x04"},
+ {"net/http/fcgi", "\x02\x01\nZ\a\x03\x80\x01\x16\x01\x01\x14\x18\x02\x0e"},
+ {"net/http/httptest", "\x02\x01\nF\x02\x1b\x01\x80\x01\x04\x12\x01\n\t\x02\x17\x01\x02\x0e\x0e"},
+ {"net/http/httptrace", "\rFnF\x14\n "},
+ {"net/http/httputil", "\x02\x01\na\x03\x80\x01\x04\x0f\x03\x01\x05\x02\x01\v\x01\x19\x02\x0e\x0e"},
+ {"net/http/internal", "\x02\x01k\x03\x80\x01"},
+ {"net/http/internal/ascii", "\xb5\x02\x12"},
+ {"net/http/internal/httpcommon", "\ra\x03\x9c\x01\x0e\x01\x17\x01\x01\x02\x1c\x02"},
+ {"net/http/internal/testcert", "\xb5\x02"},
+ {"net/http/pprof", "\x02\x01\nd\x18-\x11*\x04\x13\x14\x01\r\x04\x03\x01\x02\x01\x10"},
{"net/internal/cgotest", ""},
- {"net/internal/socktest", "p\xc2\x01\x02"},
- {"net/mail", "\x02k\x03z\x04\x0f\x03\x14\x1c\x02\r\x04"},
- {"net/netip", "\x04i+\x01#;\x026\x15"},
- {"net/rpc", "\x02f\x05\x03\x10\n`\x04\x12\x01\x1d\x0f\x03\x02"},
- {"net/rpc/jsonrpc", "j\x03\x03z\x16\x11!"},
- {"net/smtp", "\x19.\v\x13\b\x03z\x16\x14\x1c"},
- {"net/textproto", "\x02\x01j\x03z\r\t/\x01\x02\x13"},
- {"net/url", "m\x03\x86\x01%\x12\x02\x01\x15"},
- {"os", "m+\x01\x18\x03\b\t\r\x03\x01\x04\x10\x018\n\x05\x01\x01\v\x06"},
- {"os/exec", "\x03\n`H \x01\x14\x01+\x06\a\f\x01\x04\v"},
- {"os/exec/internal/fdtest", "\xb4\x02"},
- {"os/signal", "\r\x89\x02\x17\x05\x02"},
- {"os/user", "\x02\x01j\x03z,\r\f\x01\x02"},
- {"path", "m+\xab\x01"},
- {"path/filepath", "m+\x19:+\r\n\x03\x04\x0f"},
- {"plugin", "m"},
- {"reflect", "m'\x04\x1c\b\f\x04\x02\x19\x10,\f\x03\x0f\x02\x02"},
+ {"net/internal/socktest", "q\xc6\x01\x02"},
+ {"net/mail", "\x02l\x03\x80\x01\x04\x0f\x03\x14\x1a\x02\x0e\x04"},
+ {"net/netip", "\x04j*\x01$@\x034\x16"},
+ {"net/rpc", "\x02g\x05\x03\x0f\ng\x04\x12\x01\x1d\r\x03\x02"},
+ {"net/rpc/jsonrpc", "k\x03\x03\x80\x01\x16\x11\x1f"},
+ {"net/smtp", "\x19/\v\x13\b\x03\x80\x01\x16\x14\x1a"},
+ {"net/textproto", "\x02\x01k\x03\x80\x01\f\n-\x01\x02\x14"},
+ {"net/url", "n\x03\x8b\x01&\x10\x02\x01\x16"},
+ {"os", "n*\x01\x19\x03\b\t\x12\x03\x01\x05\x10\x018\b\x05\x01\x01\f\x06"},
+ {"os/exec", "\x03\naH%\x01\x15\x01+\x06\a\n\x01\x04\f"},
+ {"os/exec/internal/fdtest", "\xb9\x02"},
+ {"os/signal", "\r\x90\x02\x15\x05\x02"},
+ {"os/user", "\x02\x01k\x03\x80\x01,\r\n\x01\x02"},
+ {"path", "n*\xb1\x01"},
+ {"path/filepath", "n*\x1a@+\r\b\x03\x04\x10"},
+ {"plugin", "n"},
+ {"reflect", "n&\x04\x1d\b\f\x06\x04\x1b\x06\t-\n\x03\x10\x02\x02"},
{"reflect/internal/example1", ""},
{"reflect/internal/example2", ""},
- {"regexp", "\x03\xe7\x018\v\x02\x01\x02\x0f\x02"},
- {"regexp/syntax", "\xad\x02\x01\x01\x01\x11\x02"},
- {"runtime", "\x94\x01\x04\x01\x02\f\x06\a\x02\x01\x01\x0f\x03\x01\x01\x01\x01\x01\x03\x0fd"},
- {"runtime/coverage", "\x9f\x01K"},
- {"runtime/debug", "pUQ\r\n\x02\x01\x0f\x06"},
- {"runtime/internal/startlinetest", ""},
- {"runtime/internal/wasitest", ""},
- {"runtime/metrics", "\xb6\x01A,\""},
- {"runtime/pprof", "\x02\x01\x01\x03\x06Y\a\x03$3#\r\x1f\r\n\x01\x01\x01\x02\x02\b\x03\x06"},
- {"runtime/race", "\xab\x02"},
+ {"regexp", "\x03\xee\x018\t\x02\x01\x02\x10\x02"},
+ {"regexp/syntax", "\xb2\x02\x01\x01\x01\x02\x10\x02"},
+ {"runtime", "\x94\x01\x04\x01\x03\f\x06\a\x02\x01\x01\x0f\x03\x01\x01\x01\x01\x01\x02\x01\x01\x04\x10c"},
+ {"runtime/coverage", "\xa0\x01Q"},
+ {"runtime/debug", "qUW\r\b\x02\x01\x10\x06"},
+ {"runtime/metrics", "\xb7\x01F-!"},
+ {"runtime/pprof", "\x02\x01\x01\x03\x06Z\a\x03#4)\f \r\b\x01\x01\x01\x02\x02\t\x03\x06"},
+ {"runtime/race", "\xb0\x02"},
{"runtime/race/internal/amd64v1", ""},
- {"runtime/trace", "\rcz9\x0f\x01\x12"},
- {"slices", "\x04\xe9\x01\fL"},
- {"sort", "\xc9\x0104"},
- {"strconv", "m+:%\x02J"},
- {"strings", "m'\x04:\x18\x03\f9\x0f\x02\x02"},
+ {"runtime/trace", "\ra\x03w\t9\b\x05\x01\r\x06"},
+ {"slices", "\x04\xf0\x01\fK"},
+ {"sort", "\xca\x0162"},
+ {"strconv", "n*@%\x03I"},
+ {"strings", "n&\x04@\x19\x03\f7\x10\x02\x02"},
{"structs", ""},
- {"sync", "\xc8\x01\vP\x10\x12"},
- {"sync/atomic", "\xc5\x02"},
- {"syscall", "m(\x03\x01\x1b\b\x03\x03\x06\aT\n\x05\x01\x12"},
- {"testing", "\x03\n`\x02\x01X\x0f\x13\r\x04\x1b\x06\x02\x05\x02\a\x01\x02\x01\x02\x01\f\x02\x02\x02"},
- {"testing/fstest", "m\x03z\x01\v%\x12\x03\b\a"},
- {"testing/internal/testdeps", "\x02\v\xa6\x01'\x10,\x03\x05\x03\b\a\x02\r"},
- {"testing/iotest", "\x03j\x03z\x04"},
- {"testing/quick", "o\x01\x87\x01\x04#\x12\x0f"},
- {"testing/slogtest", "\r`\x03\x80\x01.\x05\x12\n"},
- {"text/scanner", "\x03mz,+\x02"},
- {"text/tabwriter", "pzY"},
- {"text/template", "m\x03B8\x01\v\x1f\x01\x05\x01\x02\x05\r\x02\f\x03\x02"},
- {"text/template/parse", "\x03m\xb3\x01\f\x01\x11\x02"},
- {"time", "m+\x1d\x1d'*\x0f\x02\x11"},
- {"time/tzdata", "m\xc7\x01\x11"},
+ {"sync", "\xc9\x01\x10\x01P\x0e\x13"},
+ {"sync/atomic", "\xcb\x02"},
+ {"syscall", "n'\x03\x01\x1c\b\x03\x03\x06\vV\b\x05\x01\x13"},
+ {"testing", "\x03\na\x02\x01X\x14\x14\f\x05\x1b\x06\x02\x05\x02\x05\x01\x02\x01\x02\x01\r\x02\x02\x02"},
+ {"testing/fstest", "n\x03\x80\x01\x01\n&\x10\x03\b\b"},
+ {"testing/internal/testdeps", "\x02\v\xa7\x01-\x10,\x03\x05\x03\x06\a\x02\x0e"},
+ {"testing/iotest", "\x03k\x03\x80\x01\x04"},
+ {"testing/quick", "p\x01\x8c\x01\x05#\x10\x10"},
+ {"testing/slogtest", "\ra\x03\x86\x01.\x05\x10\v"},
+ {"testing/synctest", "\xda\x01`\x11"},
+ {"text/scanner", "\x03n\x80\x01,*\x02"},
+ {"text/tabwriter", "q\x80\x01X"},
+ {"text/template", "n\x03B>\x01\n \x01\x05\x01\x02\x05\v\x02\r\x03\x02"},
+ {"text/template/parse", "\x03n\xb9\x01\n\x01\x12\x02"},
+ {"time", "n*\x1e\"(*\r\x02\x12"},
+ {"time/tzdata", "n\xcb\x01\x12"},
{"unicode", ""},
{"unicode/utf16", ""},
{"unicode/utf8", ""},
- {"unique", "\x94\x01>\x01P\x0f\x13\x12"},
+ {"unique", "\x94\x01!#\x01Q\r\x01\x13\x12"},
{"unsafe", ""},
- {"vendor/golang.org/x/crypto/chacha20", "\x10V\a\x8c\x01*'"},
- {"vendor/golang.org/x/crypto/chacha20poly1305", "\x10V\a\xd9\x01\x04\x01\a"},
- {"vendor/golang.org/x/crypto/cryptobyte", "c\n\x03\x88\x01&!\n"},
+ {"vendor/golang.org/x/crypto/chacha20", "\x10W\a\x92\x01*&"},
+ {"vendor/golang.org/x/crypto/chacha20poly1305", "\x10W\a\xde\x01\x04\x01\a"},
+ {"vendor/golang.org/x/crypto/cryptobyte", "d\n\x03\x8d\x01' \n"},
{"vendor/golang.org/x/crypto/cryptobyte/asn1", ""},
- {"vendor/golang.org/x/crypto/internal/alias", "\xc5\x02"},
- {"vendor/golang.org/x/crypto/internal/poly1305", "Q\x15\x93\x01"},
- {"vendor/golang.org/x/net/dns/dnsmessage", "m"},
- {"vendor/golang.org/x/net/http/httpguts", "\x80\x02\x14\x1c\x13\r"},
- {"vendor/golang.org/x/net/http/httpproxy", "m\x03\x90\x01\x15\x01\x1a\x13\r"},
- {"vendor/golang.org/x/net/http2/hpack", "\x03j\x03zH"},
- {"vendor/golang.org/x/net/idna", "p\x87\x019\x13\x10\x02\x01"},
- {"vendor/golang.org/x/net/nettest", "\x03c\a\x03z\x11\x05\x16\x01\f\f\x01\x02\x02\x01\n"},
- {"vendor/golang.org/x/sys/cpu", "\x96\x02\r\f\x01\x15"},
- {"vendor/golang.org/x/text/secure/bidirule", "m\xd6\x01\x11\x01"},
- {"vendor/golang.org/x/text/transform", "\x03j}Y"},
- {"vendor/golang.org/x/text/unicode/bidi", "\x03\be~@\x15"},
- {"vendor/golang.org/x/text/unicode/norm", "f\nzH\x11\x11"},
- {"weak", "\x94\x01\x8f\x01\""},
+ {"vendor/golang.org/x/crypto/internal/alias", "\xcb\x02"},
+ {"vendor/golang.org/x/crypto/internal/poly1305", "R\x15\x99\x01"},
+ {"vendor/golang.org/x/net/dns/dnsmessage", "n"},
+ {"vendor/golang.org/x/net/http/httpguts", "\x87\x02\x14\x1a\x14\r"},
+ {"vendor/golang.org/x/net/http/httpproxy", "n\x03\x96\x01\x10\x05\x01\x18\x14\r"},
+ {"vendor/golang.org/x/net/http2/hpack", "\x03k\x03\x80\x01F"},
+ {"vendor/golang.org/x/net/idna", "q\x8c\x018\x14\x10\x02\x01"},
+ {"vendor/golang.org/x/net/nettest", "\x03d\a\x03\x80\x01\x11\x05\x16\x01\f\n\x01\x02\x02\x01\v"},
+ {"vendor/golang.org/x/sys/cpu", "\x9d\x02\r\n\x01\x16"},
+ {"vendor/golang.org/x/text/secure/bidirule", "n\xdb\x01\x11\x01"},
+ {"vendor/golang.org/x/text/transform", "\x03k\x83\x01X"},
+ {"vendor/golang.org/x/text/unicode/bidi", "\x03\bf\x84\x01>\x16"},
+ {"vendor/golang.org/x/text/unicode/norm", "g\n\x80\x01F\x12\x11"},
+ {"weak", "\x94\x01\x96\x01!"},
}
diff --git a/vendor/golang.org/x/tools/internal/stdlib/manifest.go b/vendor/golang.org/x/tools/internal/stdlib/manifest.go
index 64f0326b64..c1faa50d36 100644
--- a/vendor/golang.org/x/tools/internal/stdlib/manifest.go
+++ b/vendor/golang.org/x/tools/internal/stdlib/manifest.go
@@ -502,6 +502,7 @@ var PackageSymbols = map[string][]Symbol{
{"MD4", Const, 0, ""},
{"MD5", Const, 0, ""},
{"MD5SHA1", Const, 0, ""},
+ {"MessageSigner", Type, 25, ""},
{"PrivateKey", Type, 0, ""},
{"PublicKey", Type, 2, ""},
{"RIPEMD160", Const, 0, ""},
@@ -517,6 +518,7 @@ var PackageSymbols = map[string][]Symbol{
{"SHA512", Const, 0, ""},
{"SHA512_224", Const, 5, ""},
{"SHA512_256", Const, 5, ""},
+ {"SignMessage", Func, 25, "func(signer Signer, rand io.Reader, msg []byte, opts SignerOpts) (signature []byte, err error)"},
{"Signer", Type, 4, ""},
{"SignerOpts", Type, 4, ""},
},
@@ -600,10 +602,12 @@ var PackageSymbols = map[string][]Symbol{
{"X25519", Func, 20, "func() Curve"},
},
"crypto/ecdsa": {
+ {"(*PrivateKey).Bytes", Method, 25, ""},
{"(*PrivateKey).ECDH", Method, 20, ""},
{"(*PrivateKey).Equal", Method, 15, ""},
{"(*PrivateKey).Public", Method, 4, ""},
{"(*PrivateKey).Sign", Method, 4, ""},
+ {"(*PublicKey).Bytes", Method, 25, ""},
{"(*PublicKey).ECDH", Method, 20, ""},
{"(*PublicKey).Equal", Method, 15, ""},
{"(PrivateKey).Add", Method, 0, ""},
@@ -619,6 +623,8 @@ var PackageSymbols = map[string][]Symbol{
{"(PublicKey).ScalarBaseMult", Method, 0, ""},
{"(PublicKey).ScalarMult", Method, 0, ""},
{"GenerateKey", Func, 0, "func(c elliptic.Curve, rand io.Reader) (*PrivateKey, error)"},
+ {"ParseRawPrivateKey", Func, 25, "func(curve elliptic.Curve, data []byte) (*PrivateKey, error)"},
+ {"ParseUncompressedPublicKey", Func, 25, "func(curve elliptic.Curve, data []byte) (*PublicKey, error)"},
{"PrivateKey", Type, 0, ""},
{"PrivateKey.D", Field, 0, ""},
{"PrivateKey.PublicKey", Field, 0, ""},
@@ -815,6 +821,7 @@ var PackageSymbols = map[string][]Symbol{
"crypto/sha3": {
{"(*SHA3).AppendBinary", Method, 24, ""},
{"(*SHA3).BlockSize", Method, 24, ""},
+ {"(*SHA3).Clone", Method, 25, ""},
{"(*SHA3).MarshalBinary", Method, 24, ""},
{"(*SHA3).Reset", Method, 24, ""},
{"(*SHA3).Size", Method, 24, ""},
@@ -967,6 +974,7 @@ var PackageSymbols = map[string][]Symbol{
{"Config.GetCertificate", Field, 4, ""},
{"Config.GetClientCertificate", Field, 8, ""},
{"Config.GetConfigForClient", Field, 8, ""},
+ {"Config.GetEncryptedClientHelloKeys", Field, 25, ""},
{"Config.InsecureSkipVerify", Field, 0, ""},
{"Config.KeyLogWriter", Field, 8, ""},
{"Config.MaxVersion", Field, 2, ""},
@@ -5463,6 +5471,7 @@ var PackageSymbols = map[string][]Symbol{
{"ParenExpr.X", Field, 0, ""},
{"Pkg", Const, 0, ""},
{"Preorder", Func, 23, "func(root Node) iter.Seq[Node]"},
+ {"PreorderStack", Func, 25, "func(root Node, stack []Node, f func(n Node, stack []Node) bool)"},
{"Print", Func, 0, "func(fset *token.FileSet, x any) error"},
{"RECV", Const, 0, ""},
{"RangeStmt", Type, 0, ""},
@@ -5933,6 +5942,7 @@ var PackageSymbols = map[string][]Symbol{
{"(*File).SetLines", Method, 0, ""},
{"(*File).SetLinesForContent", Method, 0, ""},
{"(*File).Size", Method, 0, ""},
+ {"(*FileSet).AddExistingFiles", Method, 25, ""},
{"(*FileSet).AddFile", Method, 0, ""},
{"(*FileSet).Base", Method, 0, ""},
{"(*FileSet).File", Method, 0, ""},
@@ -6382,7 +6392,7 @@ var PackageSymbols = map[string][]Symbol{
{"Label", Type, 5, ""},
{"LocalVar", Const, 25, ""},
{"LookupFieldOrMethod", Func, 5, "func(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool)"},
- {"LookupSelection", Func, 25, ""},
+ {"LookupSelection", Func, 25, "func(T Type, addressable bool, pkg *Package, name string) (Selection, bool)"},
{"Map", Type, 5, ""},
{"MethodExpr", Const, 5, ""},
{"MethodSet", Type, 5, ""},
@@ -6490,9 +6500,11 @@ var PackageSymbols = map[string][]Symbol{
{"Lang", Func, 22, "func(x string) string"},
},
"hash": {
+ {"Cloner", Type, 25, ""},
{"Hash", Type, 0, ""},
{"Hash32", Type, 0, ""},
{"Hash64", Type, 0, ""},
+ {"XOF", Type, 25, ""},
},
"hash/adler32": {
{"Checksum", Func, 0, "func(data []byte) uint32"},
@@ -6533,6 +6545,7 @@ var PackageSymbols = map[string][]Symbol{
},
"hash/maphash": {
{"(*Hash).BlockSize", Method, 14, ""},
+ {"(*Hash).Clone", Method, 25, ""},
{"(*Hash).Reset", Method, 14, ""},
{"(*Hash).Seed", Method, 14, ""},
{"(*Hash).SetSeed", Method, 14, ""},
@@ -7133,7 +7146,7 @@ var PackageSymbols = map[string][]Symbol{
{"FormatFileInfo", Func, 21, "func(info FileInfo) string"},
{"Glob", Func, 16, "func(fsys FS, pattern string) (matches []string, err error)"},
{"GlobFS", Type, 16, ""},
- {"Lstat", Func, 25, ""},
+ {"Lstat", Func, 25, "func(fsys FS, name string) (FileInfo, error)"},
{"ModeAppend", Const, 16, ""},
{"ModeCharDevice", Const, 16, ""},
{"ModeDevice", Const, 16, ""},
@@ -7158,7 +7171,7 @@ var PackageSymbols = map[string][]Symbol{
{"ReadDirFile", Type, 16, ""},
{"ReadFile", Func, 16, "func(fsys FS, name string) ([]byte, error)"},
{"ReadFileFS", Type, 16, ""},
- {"ReadLink", Func, 25, ""},
+ {"ReadLink", Func, 25, "func(fsys FS, name string) (string, error)"},
{"ReadLinkFS", Type, 25, ""},
{"SkipAll", Var, 20, ""},
{"SkipDir", Var, 16, ""},
@@ -7275,6 +7288,7 @@ var PackageSymbols = map[string][]Symbol{
{"(Record).Attrs", Method, 21, ""},
{"(Record).Clone", Method, 21, ""},
{"(Record).NumAttrs", Method, 21, ""},
+ {"(Record).Source", Method, 25, ""},
{"(Value).Any", Method, 21, ""},
{"(Value).Bool", Method, 21, ""},
{"(Value).Duration", Method, 21, ""},
@@ -7306,6 +7320,7 @@ var PackageSymbols = map[string][]Symbol{
{"Float64", Func, 21, "func(key string, v float64) Attr"},
{"Float64Value", Func, 21, "func(v float64) Value"},
{"Group", Func, 21, "func(key string, args ...any) Attr"},
+ {"GroupAttrs", Func, 25, "func(key string, attrs ...Attr) Attr"},
{"GroupValue", Func, 21, "func(as ...Attr) Value"},
{"Handler", Type, 21, ""},
{"HandlerOptions", Type, 21, ""},
@@ -7916,7 +7931,7 @@ var PackageSymbols = map[string][]Symbol{
{"(*Writer).WriteField", Method, 0, ""},
{"ErrMessageTooLarge", Var, 9, ""},
{"File", Type, 0, ""},
- {"FileContentDisposition", Func, 25, ""},
+ {"FileContentDisposition", Func, 25, "func(fieldname string, filename string) string"},
{"FileHeader", Type, 0, ""},
{"FileHeader.Filename", Field, 0, ""},
{"FileHeader.Header", Field, 0, ""},
@@ -8294,6 +8309,11 @@ var PackageSymbols = map[string][]Symbol{
{"(*Client).PostForm", Method, 0, ""},
{"(*Cookie).String", Method, 0, ""},
{"(*Cookie).Valid", Method, 18, ""},
+ {"(*CrossOriginProtection).AddInsecureBypassPattern", Method, 25, ""},
+ {"(*CrossOriginProtection).AddTrustedOrigin", Method, 25, ""},
+ {"(*CrossOriginProtection).Check", Method, 25, ""},
+ {"(*CrossOriginProtection).Handler", Method, 25, ""},
+ {"(*CrossOriginProtection).SetDenyHandler", Method, 25, ""},
{"(*MaxBytesError).Error", Method, 19, ""},
{"(*ProtocolError).Error", Method, 0, ""},
{"(*ProtocolError).Is", Method, 21, ""},
@@ -8388,6 +8408,7 @@ var PackageSymbols = map[string][]Symbol{
{"Cookie.Unparsed", Field, 0, ""},
{"Cookie.Value", Field, 0, ""},
{"CookieJar", Type, 0, ""},
+ {"CrossOriginProtection", Type, 25, ""},
{"DefaultClient", Var, 0, ""},
{"DefaultMaxHeaderBytes", Const, 0, ""},
{"DefaultMaxIdleConnsPerHost", Const, 0, ""},
@@ -8460,6 +8481,7 @@ var PackageSymbols = map[string][]Symbol{
{"MethodPost", Const, 6, ""},
{"MethodPut", Const, 6, ""},
{"MethodTrace", Const, 6, ""},
+ {"NewCrossOriginProtection", Func, 25, "func() *CrossOriginProtection"},
{"NewFileTransport", Func, 0, "func(fs FileSystem) RoundTripper"},
{"NewFileTransportFS", Func, 22, "func(fsys fs.FS) RoundTripper"},
{"NewRequest", Func, 0, "func(method string, url string, body io.Reader) (*Request, error)"},
@@ -9174,15 +9196,19 @@ var PackageSymbols = map[string][]Symbol{
{"(*Root).Link", Method, 25, ""},
{"(*Root).Lstat", Method, 24, ""},
{"(*Root).Mkdir", Method, 24, ""},
+ {"(*Root).MkdirAll", Method, 25, ""},
{"(*Root).Name", Method, 24, ""},
{"(*Root).Open", Method, 24, ""},
{"(*Root).OpenFile", Method, 24, ""},
{"(*Root).OpenRoot", Method, 24, ""},
+ {"(*Root).ReadFile", Method, 25, ""},
{"(*Root).Readlink", Method, 25, ""},
{"(*Root).Remove", Method, 24, ""},
+ {"(*Root).RemoveAll", Method, 25, ""},
{"(*Root).Rename", Method, 25, ""},
{"(*Root).Stat", Method, 24, ""},
{"(*Root).Symlink", Method, 25, ""},
+ {"(*Root).WriteFile", Method, 25, ""},
{"(*SyscallError).Error", Method, 0, ""},
{"(*SyscallError).Timeout", Method, 10, ""},
{"(*SyscallError).Unwrap", Method, 13, ""},
@@ -9623,6 +9649,7 @@ var PackageSymbols = map[string][]Symbol{
{"StructTag", Type, 0, ""},
{"Swapper", Func, 8, "func(slice any) func(i int, j int)"},
{"Type", Type, 0, ""},
+ {"TypeAssert", Func, 25, "func[T any](v Value) (T, bool)"},
{"TypeFor", Func, 22, "func[T any]() Type"},
{"TypeOf", Func, 0, "func(i any) Type"},
{"Uint", Const, 0, ""},
@@ -9909,6 +9936,7 @@ var PackageSymbols = map[string][]Symbol{
{"SetBlockProfileRate", Func, 1, "func(rate int)"},
{"SetCPUProfileRate", Func, 0, "func(hz int)"},
{"SetCgoTraceback", Func, 7, "func(version int, traceback unsafe.Pointer, context unsafe.Pointer, symbolizer unsafe.Pointer)"},
+ {"SetDefaultGOMAXPROCS", Func, 25, "func()"},
{"SetFinalizer", Func, 0, "func(obj any, finalizer any)"},
{"SetMutexProfileFraction", Func, 8, "func(rate int) int"},
{"Stack", Func, 0, "func(buf []byte, all bool) int"},
@@ -10021,11 +10049,20 @@ var PackageSymbols = map[string][]Symbol{
{"WriteHeapProfile", Func, 0, "func(w io.Writer) error"},
},
"runtime/trace": {
+ {"(*FlightRecorder).Enabled", Method, 25, ""},
+ {"(*FlightRecorder).Start", Method, 25, ""},
+ {"(*FlightRecorder).Stop", Method, 25, ""},
+ {"(*FlightRecorder).WriteTo", Method, 25, ""},
{"(*Region).End", Method, 11, ""},
{"(*Task).End", Method, 11, ""},
+ {"FlightRecorder", Type, 25, ""},
+ {"FlightRecorderConfig", Type, 25, ""},
+ {"FlightRecorderConfig.MaxBytes", Field, 25, ""},
+ {"FlightRecorderConfig.MinAge", Field, 25, ""},
{"IsEnabled", Func, 11, "func() bool"},
{"Log", Func, 11, "func(ctx context.Context, category string, message string)"},
{"Logf", Func, 11, "func(ctx context.Context, category string, format string, args ...any)"},
+ {"NewFlightRecorder", Func, 25, "func(cfg FlightRecorderConfig) *FlightRecorder"},
{"NewTask", Func, 11, "func(pctx context.Context, taskType string) (ctx context.Context, task *Task)"},
{"Region", Type, 11, ""},
{"Start", Func, 5, "func(w io.Writer) error"},
@@ -16642,6 +16679,7 @@ var PackageSymbols = map[string][]Symbol{
{"ValueOf", Func, 0, ""},
},
"testing": {
+ {"(*B).Attr", Method, 25, ""},
{"(*B).Chdir", Method, 24, ""},
{"(*B).Cleanup", Method, 14, ""},
{"(*B).Context", Method, 24, ""},
@@ -16658,6 +16696,7 @@ var PackageSymbols = map[string][]Symbol{
{"(*B).Logf", Method, 0, ""},
{"(*B).Loop", Method, 24, ""},
{"(*B).Name", Method, 8, ""},
+ {"(*B).Output", Method, 25, ""},
{"(*B).ReportAllocs", Method, 1, ""},
{"(*B).ReportMetric", Method, 13, ""},
{"(*B).ResetTimer", Method, 0, ""},
@@ -16674,6 +16713,7 @@ var PackageSymbols = map[string][]Symbol{
{"(*B).StopTimer", Method, 0, ""},
{"(*B).TempDir", Method, 15, ""},
{"(*F).Add", Method, 18, ""},
+ {"(*F).Attr", Method, 25, ""},
{"(*F).Chdir", Method, 24, ""},
{"(*F).Cleanup", Method, 18, ""},
{"(*F).Context", Method, 24, ""},
@@ -16689,6 +16729,7 @@ var PackageSymbols = map[string][]Symbol{
{"(*F).Log", Method, 18, ""},
{"(*F).Logf", Method, 18, ""},
{"(*F).Name", Method, 18, ""},
+ {"(*F).Output", Method, 25, ""},
{"(*F).Setenv", Method, 18, ""},
{"(*F).Skip", Method, 18, ""},
{"(*F).SkipNow", Method, 18, ""},
@@ -16697,6 +16738,7 @@ var PackageSymbols = map[string][]Symbol{
{"(*F).TempDir", Method, 18, ""},
{"(*M).Run", Method, 4, ""},
{"(*PB).Next", Method, 3, ""},
+ {"(*T).Attr", Method, 25, ""},
{"(*T).Chdir", Method, 24, ""},
{"(*T).Cleanup", Method, 14, ""},
{"(*T).Context", Method, 24, ""},
@@ -16712,6 +16754,7 @@ var PackageSymbols = map[string][]Symbol{
{"(*T).Log", Method, 0, ""},
{"(*T).Logf", Method, 0, ""},
{"(*T).Name", Method, 8, ""},
+ {"(*T).Output", Method, 25, ""},
{"(*T).Parallel", Method, 0, ""},
{"(*T).Run", Method, 7, ""},
{"(*T).Setenv", Method, 17, ""},
@@ -16834,6 +16877,10 @@ var PackageSymbols = map[string][]Symbol{
{"Run", Func, 22, "func(t *testing.T, newHandler func(*testing.T) slog.Handler, result func(*testing.T) map[string]any)"},
{"TestHandler", Func, 21, "func(h slog.Handler, results func() []map[string]any) error"},
},
+ "testing/synctest": {
+ {"Test", Func, 25, "func(t *testing.T, f func(*testing.T))"},
+ {"Wait", Func, 25, "func()"},
+ },
"text/scanner": {
{"(*Position).IsValid", Method, 0, ""},
{"(*Scanner).Init", Method, 0, ""},
@@ -17347,6 +17394,7 @@ var PackageSymbols = map[string][]Symbol{
{"CaseRange.Lo", Field, 0, ""},
{"CaseRanges", Var, 0, ""},
{"Categories", Var, 0, ""},
+ {"CategoryAliases", Var, 25, ""},
{"Caucasian_Albanian", Var, 4, ""},
{"Cc", Var, 0, ""},
{"Cf", Var, 0, ""},
@@ -17354,6 +17402,7 @@ var PackageSymbols = map[string][]Symbol{
{"Cham", Var, 0, ""},
{"Cherokee", Var, 0, ""},
{"Chorasmian", Var, 16, ""},
+ {"Cn", Var, 25, ""},
{"Co", Var, 0, ""},
{"Common", Var, 0, ""},
{"Coptic", Var, 0, ""},
@@ -17432,6 +17481,7 @@ var PackageSymbols = map[string][]Symbol{
{"Khojki", Var, 4, ""},
{"Khudawadi", Var, 4, ""},
{"L", Var, 0, ""},
+ {"LC", Var, 25, ""},
{"Lao", Var, 0, ""},
{"Latin", Var, 0, ""},
{"Lepcha", Var, 0, ""},
diff --git a/vendor/golang.org/x/tools/internal/typesinternal/fx.go b/vendor/golang.org/x/tools/internal/typesinternal/fx.go
new file mode 100644
index 0000000000..93acff2170
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/typesinternal/fx.go
@@ -0,0 +1,49 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package typesinternal
+
+import (
+ "go/ast"
+ "go/token"
+ "go/types"
+)
+
+// NoEffects reports whether the expression has no side effects, i.e., it
+// does not modify the memory state. This function is conservative: it may
+// return false even when the expression has no effect.
+func NoEffects(info *types.Info, expr ast.Expr) bool {
+ noEffects := true
+ ast.Inspect(expr, func(n ast.Node) bool {
+ switch v := n.(type) {
+ case nil, *ast.Ident, *ast.BasicLit, *ast.BinaryExpr, *ast.ParenExpr,
+ *ast.SelectorExpr, *ast.IndexExpr, *ast.SliceExpr, *ast.TypeAssertExpr,
+ *ast.StarExpr, *ast.CompositeLit, *ast.ArrayType, *ast.StructType,
+ *ast.MapType, *ast.InterfaceType, *ast.KeyValueExpr:
+ // No effect
+ case *ast.UnaryExpr:
+ // Channel send <-ch has effects
+ if v.Op == token.ARROW {
+ noEffects = false
+ }
+ case *ast.CallExpr:
+ // Type conversion has no effects
+ if !info.Types[v.Fun].IsType() {
+ // TODO(adonovan): Add a case for built-in functions without side
+ // effects (by using callsPureBuiltin from tools/internal/refactor/inline)
+
+ noEffects = false
+ }
+ case *ast.FuncLit:
+ // A FuncLit has no effects, but do not descend into it.
+ return false
+ default:
+ // All other expressions have effects
+ noEffects = false
+ }
+
+ return noEffects
+ })
+ return noEffects
+}
diff --git a/vendor/golang.org/x/tools/internal/typesinternal/isnamed.go b/vendor/golang.org/x/tools/internal/typesinternal/isnamed.go
new file mode 100644
index 0000000000..f2affec4fb
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/typesinternal/isnamed.go
@@ -0,0 +1,71 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package typesinternal
+
+import (
+ "go/types"
+ "slices"
+)
+
+// IsTypeNamed reports whether t is (or is an alias for) a
+// package-level defined type with the given package path and one of
+// the given names. It returns false if t is nil.
+//
+// This function avoids allocating the concatenation of "pkg.Name",
+// which is important for the performance of syntax matching.
+func IsTypeNamed(t types.Type, pkgPath string, names ...string) bool {
+ if named, ok := types.Unalias(t).(*types.Named); ok {
+ tname := named.Obj()
+ return tname != nil &&
+ IsPackageLevel(tname) &&
+ tname.Pkg().Path() == pkgPath &&
+ slices.Contains(names, tname.Name())
+ }
+ return false
+}
+
+// IsPointerToNamed reports whether t is (or is an alias for) a pointer to a
+// package-level defined type with the given package path and one of the given
+// names. It returns false if t is not a pointer type.
+func IsPointerToNamed(t types.Type, pkgPath string, names ...string) bool {
+ r := Unpointer(t)
+ if r == t {
+ return false
+ }
+ return IsTypeNamed(r, pkgPath, names...)
+}
+
+// IsFunctionNamed reports whether obj is a package-level function
+// defined in the given package and has one of the given names.
+// It returns false if obj is nil.
+//
+// This function avoids allocating the concatenation of "pkg.Name",
+// which is important for the performance of syntax matching.
+func IsFunctionNamed(obj types.Object, pkgPath string, names ...string) bool {
+ f, ok := obj.(*types.Func)
+ return ok &&
+ IsPackageLevel(obj) &&
+ f.Pkg().Path() == pkgPath &&
+ f.Type().(*types.Signature).Recv() == nil &&
+ slices.Contains(names, f.Name())
+}
+
+// IsMethodNamed reports whether obj is a method defined on a
+// package-level type with the given package and type name, and has
+// one of the given names. It returns false if obj is nil.
+//
+// This function avoids allocating the concatenation of "pkg.TypeName.Name",
+// which is important for the performance of syntax matching.
+func IsMethodNamed(obj types.Object, pkgPath string, typeName string, names ...string) bool {
+ if fn, ok := obj.(*types.Func); ok {
+ if recv := fn.Type().(*types.Signature).Recv(); recv != nil {
+ _, T := ReceiverNamed(recv)
+ return T != nil &&
+ IsTypeNamed(T, pkgPath, typeName) &&
+ slices.Contains(names, fn.Name())
+ }
+ }
+ return false
+}
diff --git a/vendor/golang.org/x/tools/internal/typesinternal/qualifier.go b/vendor/golang.org/x/tools/internal/typesinternal/qualifier.go
index b64f714eb3..64f47919f0 100644
--- a/vendor/golang.org/x/tools/internal/typesinternal/qualifier.go
+++ b/vendor/golang.org/x/tools/internal/typesinternal/qualifier.go
@@ -15,6 +15,14 @@ import (
// file.
// If the same package is imported multiple times, the last appearance is
// recorded.
+//
+// TODO(adonovan): this function ignores the effect of shadowing. It
+// should accept a [token.Pos] and a [types.Info] and compute only the
+// set of imports that are not shadowed at that point, analogous to
+// [analysisinternal.AddImport]. It could also compute (as a side
+// effect) the set of additional imports required to ensure that there
+// is an accessible import for each necessary package, making it
+// converge even more closely with AddImport.
func FileQualifier(f *ast.File, pkg *types.Package) types.Qualifier {
// Construct mapping of import paths to their defined names.
// It is only necessary to look at renaming imports.
diff --git a/vendor/golang.org/x/tools/internal/typesinternal/types.go b/vendor/golang.org/x/tools/internal/typesinternal/types.go
index a5cd7e8dbf..fef74a7856 100644
--- a/vendor/golang.org/x/tools/internal/typesinternal/types.go
+++ b/vendor/golang.org/x/tools/internal/typesinternal/types.go
@@ -2,8 +2,20 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Package typesinternal provides access to internal go/types APIs that are not
-// yet exported.
+// Package typesinternal provides helpful operators for dealing with
+// go/types:
+//
+// - operators for querying typed syntax trees (e.g. [Imports], [IsFunctionNamed]);
+// - functions for converting types to strings or syntax (e.g. [TypeExpr], FileQualifier]);
+// - helpers for working with the [go/types] API (e.g. [NewTypesInfo]);
+// - access to internal go/types APIs that are not yet
+// exported (e.g. [SetUsesCgo], [ErrorCodeStartEnd], [VarKind]); and
+// - common algorithms related to types (e.g. [TooNewStdSymbols]).
+//
+// See also:
+// - [golang.org/x/tools/internal/astutil], for operations on untyped syntax;
+// - [golang.org/x/tools/internal/analysisinernal], for helpers for analyzers;
+// - [golang.org/x/tools/internal/refactor], for operators to compute text edits.
package typesinternal
import (
@@ -13,6 +25,7 @@ import (
"reflect"
"unsafe"
+ "golang.org/x/tools/go/ast/inspector"
"golang.org/x/tools/internal/aliases"
)
@@ -60,6 +73,9 @@ func ErrorCodeStartEnd(err types.Error) (code ErrorCode, start, end token.Pos, o
// which is often excessive.)
//
// If pkg is nil, it is equivalent to [*types.Package.Name].
+//
+// TODO(adonovan): all uses of this with TypeString should be
+// eliminated when https://go.dev/issues/75604 is resolved.
func NameRelativeTo(pkg *types.Package) types.Qualifier {
return func(other *types.Package) string {
if pkg != nil && pkg == other {
@@ -153,3 +169,31 @@ func NewTypesInfo() *types.Info {
FileVersions: map[*ast.File]string{},
}
}
+
+// EnclosingScope returns the innermost block logically enclosing the cursor.
+func EnclosingScope(info *types.Info, cur inspector.Cursor) *types.Scope {
+ for cur := range cur.Enclosing() {
+ n := cur.Node()
+ // A function's Scope is associated with its FuncType.
+ switch f := n.(type) {
+ case *ast.FuncDecl:
+ n = f.Type
+ case *ast.FuncLit:
+ n = f.Type
+ }
+ if b := info.Scopes[n]; b != nil {
+ return b
+ }
+ }
+ panic("no Scope for *ast.File")
+}
+
+// Imports reports whether path is imported by pkg.
+func Imports(pkg *types.Package, path string) bool {
+ for _, imp := range pkg.Imports() {
+ if imp.Path() == path {
+ return true
+ }
+ }
+ return false
+}
diff --git a/vendor/golang.org/x/tools/internal/typesinternal/zerovalue.go b/vendor/golang.org/x/tools/internal/typesinternal/zerovalue.go
index d272949c17..453bba2ad5 100644
--- a/vendor/golang.org/x/tools/internal/typesinternal/zerovalue.go
+++ b/vendor/golang.org/x/tools/internal/typesinternal/zerovalue.go
@@ -204,23 +204,12 @@ func ZeroExpr(t types.Type, qual types.Qualifier) (_ ast.Expr, isValid bool) {
}
}
-// IsZeroExpr uses simple syntactic heuristics to report whether expr
-// is a obvious zero value, such as 0, "", nil, or false.
-// It cannot do better without type information.
-func IsZeroExpr(expr ast.Expr) bool {
- switch e := expr.(type) {
- case *ast.BasicLit:
- return e.Value == "0" || e.Value == `""`
- case *ast.Ident:
- return e.Name == "nil" || e.Name == "false"
- default:
- return false
- }
-}
-
// TypeExpr returns syntax for the specified type. References to named types
// are qualified by an appropriate (optional) qualifier function.
// It may panic for types such as Tuple or Union.
+//
+// See also https://go.dev/issues/75604, which will provide a robust
+// Type-to-valid-Go-syntax formatter.
func TypeExpr(t types.Type, qual types.Qualifier) ast.Expr {
switch t := t.(type) {
case *types.Basic:
diff --git a/vendor/gopkg.in/evanphx/json-patch.v4/README.md b/vendor/gopkg.in/evanphx/json-patch.v4/README.md
index 28e3516937..86fefd5bf7 100644
--- a/vendor/gopkg.in/evanphx/json-patch.v4/README.md
+++ b/vendor/gopkg.in/evanphx/json-patch.v4/README.md
@@ -4,7 +4,7 @@
well as for calculating & applying [RFC7396 JSON merge patches](https://tools.ietf.org/html/rfc7396).
[](http://godoc.org/github.com/evanphx/json-patch)
-[](https://travis-ci.org/evanphx/json-patch)
+[](https://github.com/evanphx/json-patch/actions/workflows/go.yml)
[](https://goreportcard.com/report/github.com/evanphx/json-patch)
# Get It!
@@ -14,9 +14,7 @@ well as for calculating & applying [RFC7396 JSON merge patches](https://tools.ie
go get -u github.com/evanphx/json-patch/v5
```
-**Stable Versions**:
-* Version 5: `go get -u gopkg.in/evanphx/json-patch.v5`
-* Version 4: `go get -u gopkg.in/evanphx/json-patch.v4`
+If you need version 4, use `go get -u gopkg.in/evanphx/json-patch.v4`
(previous versions below `v3` are unavailable)
@@ -314,4 +312,4 @@ go test -cover ./...
```
Builds for pull requests are tested automatically
-using [TravisCI](https://travis-ci.org/evanphx/json-patch).
+using [GitHub Actions](https://github.com/evanphx/json-patch/actions/workflows/go.yml).
diff --git a/vendor/gopkg.in/evanphx/json-patch.v4/patch.go b/vendor/gopkg.in/evanphx/json-patch.v4/patch.go
index dc2b7e51e6..95136681ba 100644
--- a/vendor/gopkg.in/evanphx/json-patch.v4/patch.go
+++ b/vendor/gopkg.in/evanphx/json-patch.v4/patch.go
@@ -3,11 +3,10 @@ package jsonpatch
import (
"bytes"
"encoding/json"
+ "errors"
"fmt"
"strconv"
"strings"
-
- "github.com/pkg/errors"
)
const (
@@ -277,7 +276,7 @@ func (o Operation) Path() (string, error) {
return op, nil
}
- return "unknown", errors.Wrapf(ErrMissing, "operation missing path field")
+ return "unknown", fmt.Errorf("operation missing path field: %w", ErrMissing)
}
// From reads the "from" field of the Operation.
@@ -294,7 +293,7 @@ func (o Operation) From() (string, error) {
return op, nil
}
- return "unknown", errors.Wrapf(ErrMissing, "operation, missing from field")
+ return "unknown", fmt.Errorf("operation, missing from field: %w", ErrMissing)
}
func (o Operation) value() *lazyNode {
@@ -319,7 +318,7 @@ func (o Operation) ValueInterface() (interface{}, error) {
return v, nil
}
- return nil, errors.Wrapf(ErrMissing, "operation, missing value field")
+ return nil, fmt.Errorf("operation, missing value field: %w", ErrMissing)
}
func isArray(buf []byte) bool {
@@ -359,7 +358,7 @@ func findObject(pd *container, path string) (container, string) {
next, ok := doc.get(decodePatchKey(part))
- if next == nil || ok != nil {
+ if next == nil || ok != nil || next.raw == nil {
return nil, ""
}
@@ -398,7 +397,7 @@ func (d *partialDoc) get(key string) (*lazyNode, error) {
func (d *partialDoc) remove(key string) error {
_, ok := (*d)[key]
if !ok {
- return errors.Wrapf(ErrMissing, "Unable to remove nonexistent key: %s", key)
+ return fmt.Errorf("Unable to remove nonexistent key: %s: %w", key, ErrMissing)
}
delete(*d, key)
@@ -415,10 +414,10 @@ func (d *partialArray) set(key string, val *lazyNode) error {
if idx < 0 {
if !SupportNegativeIndices {
- return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+ return fmt.Errorf("Unable to access invalid index: %d: %w", idx, ErrInvalidIndex)
}
if idx < -len(*d) {
- return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+ return fmt.Errorf("Unable to access invalid index: %d: %w", idx, ErrInvalidIndex)
}
idx += len(*d)
}
@@ -435,7 +434,7 @@ func (d *partialArray) add(key string, val *lazyNode) error {
idx, err := strconv.Atoi(key)
if err != nil {
- return errors.Wrapf(err, "value was not a proper array index: '%s'", key)
+ return fmt.Errorf("value was not a proper array index: '%s': %w", key, err)
}
sz := len(*d) + 1
@@ -445,15 +444,15 @@ func (d *partialArray) add(key string, val *lazyNode) error {
cur := *d
if idx >= len(ary) {
- return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+ return fmt.Errorf("Unable to access invalid index: %d: %w", idx, ErrInvalidIndex)
}
if idx < 0 {
if !SupportNegativeIndices {
- return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+ return fmt.Errorf("Unable to access invalid index: %d: %w", idx, ErrInvalidIndex)
}
if idx < -len(ary) {
- return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+ return fmt.Errorf("Unable to access invalid index: %d: %w", idx, ErrInvalidIndex)
}
idx += len(ary)
}
@@ -475,16 +474,16 @@ func (d *partialArray) get(key string) (*lazyNode, error) {
if idx < 0 {
if !SupportNegativeIndices {
- return nil, errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+ return nil, fmt.Errorf("Unable to access invalid index: %d: %w", idx, ErrInvalidIndex)
}
if idx < -len(*d) {
- return nil, errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+ return nil, fmt.Errorf("Unable to access invalid index: %d: %w", idx, ErrInvalidIndex)
}
idx += len(*d)
}
if idx >= len(*d) {
- return nil, errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+ return nil, fmt.Errorf("Unable to access invalid index: %d: %w", idx, ErrInvalidIndex)
}
return (*d)[idx], nil
@@ -499,15 +498,15 @@ func (d *partialArray) remove(key string) error {
cur := *d
if idx >= len(cur) {
- return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+ return fmt.Errorf("Unable to access invalid index: %d: %w", idx, ErrInvalidIndex)
}
if idx < 0 {
if !SupportNegativeIndices {
- return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+ return fmt.Errorf("Unable to access invalid index: %d: %w", idx, ErrInvalidIndex)
}
if idx < -len(cur) {
- return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+ return fmt.Errorf("Unable to access invalid index: %d: %w", idx, ErrInvalidIndex)
}
idx += len(cur)
}
@@ -525,18 +524,18 @@ func (d *partialArray) remove(key string) error {
func (p Patch) add(doc *container, op Operation) error {
path, err := op.Path()
if err != nil {
- return errors.Wrapf(ErrMissing, "add operation failed to decode path")
+ return fmt.Errorf("add operation failed to decode path: %w", ErrMissing)
}
con, key := findObject(doc, path)
if con == nil {
- return errors.Wrapf(ErrMissing, "add operation does not apply: doc is missing path: \"%s\"", path)
+ return fmt.Errorf("add operation does not apply: doc is missing path: \"%s\": %w", path, ErrMissing)
}
err = con.add(key, op.value())
if err != nil {
- return errors.Wrapf(err, "error in add for path: '%s'", path)
+ return fmt.Errorf("error in add for path: '%s': %w", path, err)
}
return nil
@@ -545,18 +544,18 @@ func (p Patch) add(doc *container, op Operation) error {
func (p Patch) remove(doc *container, op Operation) error {
path, err := op.Path()
if err != nil {
- return errors.Wrapf(ErrMissing, "remove operation failed to decode path")
+ return fmt.Errorf("remove operation failed to decode path: %w", ErrMissing)
}
con, key := findObject(doc, path)
if con == nil {
- return errors.Wrapf(ErrMissing, "remove operation does not apply: doc is missing path: \"%s\"", path)
+ return fmt.Errorf("remove operation does not apply: doc is missing path: \"%s\": %w", path, ErrMissing)
}
err = con.remove(key)
if err != nil {
- return errors.Wrapf(err, "error in remove for path: '%s'", path)
+ return fmt.Errorf("error in remove for path: '%s': %w", path, err)
}
return nil
@@ -565,7 +564,7 @@ func (p Patch) remove(doc *container, op Operation) error {
func (p Patch) replace(doc *container, op Operation) error {
path, err := op.Path()
if err != nil {
- return errors.Wrapf(err, "replace operation failed to decode path")
+ return fmt.Errorf("replace operation failed to decode path: %w", err)
}
if path == "" {
@@ -574,7 +573,7 @@ func (p Patch) replace(doc *container, op Operation) error {
if val.which == eRaw {
if !val.tryDoc() {
if !val.tryAry() {
- return errors.Wrapf(err, "replace operation value must be object or array")
+ return fmt.Errorf("replace operation value must be object or array: %w", err)
}
}
}
@@ -585,7 +584,7 @@ func (p Patch) replace(doc *container, op Operation) error {
case eDoc:
*doc = &val.doc
case eRaw:
- return errors.Wrapf(err, "replace operation hit impossible case")
+ return fmt.Errorf("replace operation hit impossible case: %w", err)
}
return nil
@@ -594,17 +593,17 @@ func (p Patch) replace(doc *container, op Operation) error {
con, key := findObject(doc, path)
if con == nil {
- return errors.Wrapf(ErrMissing, "replace operation does not apply: doc is missing path: %s", path)
+ return fmt.Errorf("replace operation does not apply: doc is missing path: %s: %w", path, ErrMissing)
}
_, ok := con.get(key)
if ok != nil {
- return errors.Wrapf(ErrMissing, "replace operation does not apply: doc is missing key: %s", path)
+ return fmt.Errorf("replace operation does not apply: doc is missing key: %s: %w", path, ErrMissing)
}
err = con.set(key, op.value())
if err != nil {
- return errors.Wrapf(err, "error in remove for path: '%s'", path)
+ return fmt.Errorf("error in remove for path: '%s': %w", path, err)
}
return nil
@@ -613,39 +612,39 @@ func (p Patch) replace(doc *container, op Operation) error {
func (p Patch) move(doc *container, op Operation) error {
from, err := op.From()
if err != nil {
- return errors.Wrapf(err, "move operation failed to decode from")
+ return fmt.Errorf("move operation failed to decode from: %w", err)
}
con, key := findObject(doc, from)
if con == nil {
- return errors.Wrapf(ErrMissing, "move operation does not apply: doc is missing from path: %s", from)
+ return fmt.Errorf("move operation does not apply: doc is missing from path: %s: %w", from, ErrMissing)
}
val, err := con.get(key)
if err != nil {
- return errors.Wrapf(err, "error in move for path: '%s'", key)
+ return fmt.Errorf("error in move for path: '%s': %w", key, err)
}
err = con.remove(key)
if err != nil {
- return errors.Wrapf(err, "error in move for path: '%s'", key)
+ return fmt.Errorf("error in move for path: '%s': %w", key, err)
}
path, err := op.Path()
if err != nil {
- return errors.Wrapf(err, "move operation failed to decode path")
+ return fmt.Errorf("move operation failed to decode path: %w", err)
}
con, key = findObject(doc, path)
if con == nil {
- return errors.Wrapf(ErrMissing, "move operation does not apply: doc is missing destination path: %s", path)
+ return fmt.Errorf("move operation does not apply: doc is missing destination path: %s: %w", path, ErrMissing)
}
err = con.add(key, val)
if err != nil {
- return errors.Wrapf(err, "error in move for path: '%s'", path)
+ return fmt.Errorf("error in move for path: '%s': %w", path, err)
}
return nil
@@ -654,7 +653,7 @@ func (p Patch) move(doc *container, op Operation) error {
func (p Patch) test(doc *container, op Operation) error {
path, err := op.Path()
if err != nil {
- return errors.Wrapf(err, "test operation failed to decode path")
+ return fmt.Errorf("test operation failed to decode path: %w", err)
}
if path == "" {
@@ -673,67 +672,67 @@ func (p Patch) test(doc *container, op Operation) error {
return nil
}
- return errors.Wrapf(ErrTestFailed, "testing value %s failed", path)
+ return fmt.Errorf("testing value %s failed: %w", path, ErrTestFailed)
}
con, key := findObject(doc, path)
if con == nil {
- return errors.Wrapf(ErrMissing, "test operation does not apply: is missing path: %s", path)
+ return fmt.Errorf("test operation does not apply: is missing path: %s: %w", path, ErrMissing)
}
val, err := con.get(key)
if err != nil {
- return errors.Wrapf(err, "error in test for path: '%s'", path)
+ return fmt.Errorf("error in test for path: '%s': %w", path, err)
}
if val == nil {
- if op.value().raw == nil {
+ if op.value() == nil || op.value().raw == nil {
return nil
}
- return errors.Wrapf(ErrTestFailed, "testing value %s failed", path)
+ return fmt.Errorf("testing value %s failed: %w", path, ErrTestFailed)
} else if op.value() == nil {
- return errors.Wrapf(ErrTestFailed, "testing value %s failed", path)
+ return fmt.Errorf("testing value %s failed: %w", path, ErrTestFailed)
}
if val.equal(op.value()) {
return nil
}
- return errors.Wrapf(ErrTestFailed, "testing value %s failed", path)
+ return fmt.Errorf("testing value %s failed: %w", path, ErrTestFailed)
}
func (p Patch) copy(doc *container, op Operation, accumulatedCopySize *int64) error {
from, err := op.From()
if err != nil {
- return errors.Wrapf(err, "copy operation failed to decode from")
+ return fmt.Errorf("copy operation failed to decode from: %w", err)
}
con, key := findObject(doc, from)
if con == nil {
- return errors.Wrapf(ErrMissing, "copy operation does not apply: doc is missing from path: %s", from)
+ return fmt.Errorf("copy operation does not apply: doc is missing from path: %s: %w", from, ErrMissing)
}
val, err := con.get(key)
if err != nil {
- return errors.Wrapf(err, "error in copy for from: '%s'", from)
+ return fmt.Errorf("error in copy for from: '%s': %w", from, err)
}
path, err := op.Path()
if err != nil {
- return errors.Wrapf(ErrMissing, "copy operation failed to decode path")
+ return fmt.Errorf("copy operation failed to decode path: %w", ErrMissing)
}
con, key = findObject(doc, path)
if con == nil {
- return errors.Wrapf(ErrMissing, "copy operation does not apply: doc is missing destination path: %s", path)
+ return fmt.Errorf("copy operation does not apply: doc is missing destination path: %s: %w", path, ErrMissing)
}
valCopy, sz, err := deepCopy(val)
if err != nil {
- return errors.Wrapf(err, "error while performing deep copy")
+ return fmt.Errorf("error while performing deep copy: %w", err)
}
(*accumulatedCopySize) += int64(sz)
@@ -743,7 +742,7 @@ func (p Patch) copy(doc *container, op Operation, accumulatedCopySize *int64) er
err = con.add(key, valCopy)
if err != nil {
- return errors.Wrapf(err, "error while adding value during copy")
+ return fmt.Errorf("error while adding value during copy: %w", err)
}
return nil
diff --git a/vendor/k8s.io/kube-openapi/cmd/openapi-gen/args/args.go b/vendor/k8s.io/kube-openapi/cmd/openapi-gen/args/args.go
index 153784ed9b..7634c727b3 100644
--- a/vendor/k8s.io/kube-openapi/cmd/openapi-gen/args/args.go
+++ b/vendor/k8s.io/kube-openapi/cmd/openapi-gen/args/args.go
@@ -33,6 +33,12 @@ type Args struct {
// by API linter. If specified, API rule violations will be printed to report file.
// Otherwise default value "-" will be used which indicates stdout.
ReportFilename string
+
+ // OutputModelNameFile is the name of the file to be generated for OpenAPI schema name
+ // accessor functions. If empty, no model name accessor functions are generated.
+ // When this is specified, the OpenAPI spec generator will use the function names
+ // instead of Go type names for schema names.
+ OutputModelNameFile string
}
// New returns default arguments for the generator. Returning the arguments instead
@@ -54,6 +60,13 @@ func (args *Args) AddFlags(fs *pflag.FlagSet) {
"the base Go import-path under which to generate results")
fs.StringVar(&args.OutputFile, "output-file", "generated.openapi.go",
"the name of the file to be generated")
+ fs.StringVar(&args.OutputModelNameFile, "output-model-name-file", "",
+ `The filename for generated model name accessor functions.
+If specified, a file with this name will be created in each package containing
+a "+k8s:openapi-model-package" tag. The generated functions return fully qualified
+model names, which are used in the OpenAPI spec as schema references instead of
+Go type names. If empty, no model name accessor functions are generated and names
+are inferred from Go type names.`)
fs.StringVar(&args.GoHeaderFile, "go-header-file", "",
"the path to a file containing boilerplate header text; the string \"YEAR\" will be replaced with the current 4-digit year")
fs.StringVarP(&args.ReportFilename, "report-filename", "r", args.ReportFilename,
diff --git a/vendor/k8s.io/kube-openapi/cmd/openapi-gen/openapi-gen.go b/vendor/k8s.io/kube-openapi/cmd/openapi-gen/openapi-gen.go
index b466019ad6..b19da6f63b 100644
--- a/vendor/k8s.io/kube-openapi/cmd/openapi-gen/openapi-gen.go
+++ b/vendor/k8s.io/kube-openapi/cmd/openapi-gen/openapi-gen.go
@@ -25,6 +25,7 @@ import (
"log"
"github.com/spf13/pflag"
+
"k8s.io/gengo/v2"
"k8s.io/gengo/v2/generator"
"k8s.io/klog/v2"
@@ -45,15 +46,35 @@ func main() {
log.Fatalf("Arguments validation error: %v", err)
}
- myTargets := func(context *generator.Context) []generator.Target {
- return generators.GetTargets(context, args)
+ boilerplate, err := gengo.GoBoilerplate(args.GoHeaderFile, gengo.StdBuildTag, gengo.StdGeneratedBy)
+ if err != nil {
+ log.Fatalf("Failed loading boilerplate: %v", err)
+ }
+
+ // Generates the code for model name accessors.
+ if len(args.OutputModelNameFile) > 0 {
+ modelNameTargets := func(context *generator.Context) []generator.Target {
+ return generators.GetModelNameTargets(context, args, boilerplate)
+ }
+ if err := gengo.Execute(
+ generators.NameSystems(),
+ generators.DefaultNameSystem(),
+ modelNameTargets,
+ gengo.StdBuildTag,
+ pflag.Args(),
+ ); err != nil {
+ log.Fatalf("Model name code generation error: %v", err)
+ }
}
// Generates the code for the OpenAPIDefinitions.
+ openAPITargets := func(context *generator.Context) []generator.Target {
+ return generators.GetOpenAPITargets(context, args, boilerplate)
+ }
if err := gengo.Execute(
generators.NameSystems(),
generators.DefaultNameSystem(),
- myTargets,
+ openAPITargets,
gengo.StdBuildTag,
pflag.Args(),
); err != nil {
diff --git a/vendor/k8s.io/kube-openapi/pkg/generators/config.go b/vendor/k8s.io/kube-openapi/pkg/generators/config.go
index 1fbd775985..1bcf2a5231 100644
--- a/vendor/k8s.io/kube-openapi/pkg/generators/config.go
+++ b/vendor/k8s.io/kube-openapi/pkg/generators/config.go
@@ -19,7 +19,6 @@ package generators
import (
"path"
- "k8s.io/gengo/v2"
"k8s.io/gengo/v2/generator"
"k8s.io/gengo/v2/namer"
"k8s.io/gengo/v2/types"
@@ -49,12 +48,8 @@ func DefaultNameSystem() string {
return "sorting_namer"
}
-func GetTargets(context *generator.Context, args *args.Args) []generator.Target {
- boilerplate, err := gengo.GoBoilerplate(args.GoHeaderFile, gengo.StdBuildTag, gengo.StdGeneratedBy)
- if err != nil {
- klog.Fatalf("Failed loading boilerplate: %v", err)
- }
-
+// GetOpenAPITargets returns the targets for OpenAPI definition generation.
+func GetOpenAPITargets(context *generator.Context, args *args.Args, boilerplate []byte) []generator.Target {
reportPath := "-"
if args.ReportFilename != "" {
reportPath = args.ReportFilename
@@ -82,3 +77,56 @@ func GetTargets(context *generator.Context, args *args.Args) []generator.Target
},
}
}
+
+// GetModelNameTargets returns the targets for model name generation.
+func GetModelNameTargets(context *generator.Context, args *args.Args, boilerplate []byte) []generator.Target {
+ var targets []generator.Target
+ for _, i := range context.Inputs {
+ klog.V(5).Infof("Considering pkg %q", i)
+
+ pkg := context.Universe[i]
+
+ openAPISchemaNamePackage, err := extractOpenAPISchemaNamePackage(pkg.Comments)
+ if err != nil {
+ klog.Fatalf("Package %v: invalid %s:%v", i, tagModelPackage, err)
+ }
+ hasPackageTag := len(openAPISchemaNamePackage) > 0
+
+ hasCandidates := false
+ for _, t := range pkg.Types {
+ v, err := singularTag(tagModelPackage, t.CommentLines)
+ if err != nil {
+ klog.Fatalf("Type %v: invalid %s:%v", t.Name, tagModelPackage, err)
+ }
+ hasTag := hasPackageTag || v != nil
+ hasModel := isSchemaNameType(t)
+ if hasModel && hasTag {
+ hasCandidates = true
+ break
+ }
+ }
+ if !hasCandidates {
+ klog.V(5).Infof(" skipping package")
+ continue
+ }
+
+ klog.V(3).Infof("Generating package %q", pkg.Path)
+
+ targets = append(targets,
+ &generator.SimpleTarget{
+ PkgName: path.Base(pkg.Path),
+ PkgPath: pkg.Path,
+ PkgDir: pkg.Dir, // output pkg is the same as the input
+ HeaderComment: boilerplate,
+ FilterFunc: func(c *generator.Context, t *types.Type) bool {
+ return t.Name.Package == pkg.Path
+ },
+ GeneratorsFunc: func(c *generator.Context) (generators []generator.Generator) {
+ return []generator.Generator{
+ NewSchemaNameGen(args.OutputModelNameFile, pkg.Path, openAPISchemaNamePackage),
+ }
+ },
+ })
+ }
+ return targets
+}
diff --git a/vendor/k8s.io/kube-openapi/pkg/generators/model_names.go b/vendor/k8s.io/kube-openapi/pkg/generators/model_names.go
new file mode 100644
index 0000000000..783e975d44
--- /dev/null
+++ b/vendor/k8s.io/kube-openapi/pkg/generators/model_names.go
@@ -0,0 +1,177 @@
+/*
+Copyright 2025 The Kubernetes 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 generators
+
+import (
+ "fmt"
+ "io"
+ "strings"
+
+ "k8s.io/gengo/v2"
+ "k8s.io/gengo/v2/generator"
+ "k8s.io/gengo/v2/namer"
+ "k8s.io/gengo/v2/types"
+ "k8s.io/klog/v2"
+)
+
+const (
+ tagModelPackage = "k8s:openapi-model-package"
+)
+
+func extractOpenAPISchemaNamePackage(comments []string) (string, error) {
+ v, err := singularTag(tagModelPackage, comments)
+ if v == nil || err != nil {
+ return "", err
+ }
+ return v.Value, nil
+}
+
+func singularTag(tagName string, comments []string) (*gengo.Tag, error) {
+ tags, err := gengo.ExtractFunctionStyleCommentTags("+", []string{tagName}, comments)
+ if err != nil {
+ return nil, err
+ }
+ if len(tags) == 0 {
+ return nil, nil
+ }
+ if len(tags) > 1 {
+ return nil, fmt.Errorf("multiple %s tags found", tagName)
+ }
+ tag := tags[tagName]
+ if len(tag) == 0 {
+ return nil, nil
+ }
+ if len(tag) > 1 {
+ klog.V(5).Infof("multiple %s tags found, using the first one", tagName)
+ }
+ value := tag[0]
+ return &value, nil
+}
+
+// genSchemaName produces a file with autogenerated openapi schema name functions.
+type genSchemaName struct {
+ generator.GoGenerator
+ targetPackage string
+ imports namer.ImportTracker
+ typesForInit []*types.Type
+ openAPISchemaNamePackage string
+}
+
+// NewSchemaNameGen creates a generator
+func NewSchemaNameGen(outputFilename, targetPackage string, openAPISchemaNamePackage string) generator.Generator {
+ return &genSchemaName{
+ GoGenerator: generator.GoGenerator{
+ OutputFilename: outputFilename,
+ },
+ targetPackage: targetPackage,
+ imports: generator.NewImportTracker(),
+ typesForInit: make([]*types.Type, 0),
+ openAPISchemaNamePackage: openAPISchemaNamePackage,
+ }
+}
+
+func (g *genSchemaName) Namers(c *generator.Context) namer.NameSystems {
+ return namer.NameSystems{
+ "public": namer.NewPublicNamer(1),
+ "local": namer.NewPublicNamer(0),
+ "raw": namer.NewRawNamer("", nil),
+ }
+}
+
+func (g *genSchemaName) Filter(c *generator.Context, t *types.Type) bool {
+ // Filter out types not being processed or not copyable within the package.
+ if !isSchemaNameType(t) {
+ klog.V(2).Infof("Type %v is not a valid target for OpenAPI schema name", t)
+ return false
+ }
+ g.typesForInit = append(g.typesForInit, t)
+ return true
+}
+
+// isSchemaNameType indicates whether or not a type could be used to serve an API.
+func isSchemaNameType(t *types.Type) bool {
+ // Filter out private types.
+ if namer.IsPrivateGoName(t.Name.Name) {
+ return false
+ }
+
+ for t.Kind == types.Alias {
+ t = t.Underlying
+ }
+
+ if t.Kind != types.Struct {
+ return false
+ }
+ return true
+}
+
+func (g *genSchemaName) isOtherPackage(pkg string) bool {
+ if pkg == g.targetPackage {
+ return false
+ }
+ if strings.HasSuffix(pkg, ""+g.targetPackage+"") {
+ return false
+ }
+ return true
+}
+
+func (g *genSchemaName) Imports(c *generator.Context) (imports []string) {
+ importLines := []string{}
+ for _, singleImport := range g.imports.ImportLines() {
+ if g.isOtherPackage(singleImport) {
+ importLines = append(importLines, singleImport)
+ }
+ }
+ return importLines
+}
+
+func (g *genSchemaName) Init(c *generator.Context, w io.Writer) error {
+ return nil
+}
+
+func (g *genSchemaName) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
+ klog.V(3).Infof("Generating openapi schema name for type %v", t)
+
+ openAPISchemaNamePackage := g.openAPISchemaNamePackage
+ v, err := singularTag(tagModelPackage, t.CommentLines)
+ if err != nil {
+ return fmt.Errorf("type %v: invalid %s:%v", t.Name, tagModelPackage, err)
+ }
+ if v != nil && v.Value != "" {
+ openAPISchemaNamePackage = v.Value
+ }
+
+ if openAPISchemaNamePackage == "" {
+ return nil
+ }
+
+ schemaName := openAPISchemaNamePackage + "." + t.Name.Name
+
+ a := map[string]interface{}{
+ "type": t,
+ "schemaName": schemaName,
+ }
+
+ sw := generator.NewSnippetWriter(w, c, "$", "$")
+
+ sw.Do("// OpenAPIModelName returns the OpenAPI model name for this type.\n", a)
+ sw.Do("func (in $.type|local$) OpenAPIModelName() string {\n", a)
+ sw.Do("\treturn \"$.schemaName$\"\n", a)
+ sw.Do("}\n\n", nil)
+
+ return sw.Error()
+}
diff --git a/vendor/k8s.io/kube-openapi/pkg/generators/openapi.go b/vendor/k8s.io/kube-openapi/pkg/generators/openapi.go
index c5c0093818..5d58754a77 100644
--- a/vendor/k8s.io/kube-openapi/pkg/generators/openapi.go
+++ b/vendor/k8s.io/kube-openapi/pkg/generators/openapi.go
@@ -295,6 +295,40 @@ func hasOpenAPIV3OneOfMethod(t *types.Type) bool {
return false
}
+func hasOpenAPIModelName(t *types.Type) bool {
+ for mn, mt := range t.Methods {
+ if mn != "OpenAPIModelName" {
+ continue
+ }
+ return methodReturnsValue(mt, "", "string")
+ }
+ return false
+}
+
+func (g openAPITypeWriter) shouldUseOpenAPIModelName(t *types.Type) bool {
+ // Finds non-generated OpenAPIModelName() functions.
+ // Generated OpenAPIModelName() are ignored due to the 'ignore_autogenerated' build tag
+ // but are handled below by checking for use of the +k8s:openapi-model-package.
+ // This approach allows code generators to be called in any order.
+ if hasOpenAPIModelName(t) {
+ return true
+ }
+
+ value, err := extractOpenAPISchemaNamePackage(t.CommentLines)
+ if err != nil {
+ klog.Fatalf("Type %v: invalid %s:%v", t, tagModelPackage, err)
+ }
+ if value != "" {
+ return true
+ }
+ pkg := g.context.Universe.Package(t.Name.Package)
+ value, err = extractOpenAPISchemaNamePackage(pkg.Comments)
+ if err != nil {
+ klog.Fatalf("Package %v: invalid %s:%v", pkg, tagModelPackage, err)
+ }
+ return value != ""
+}
+
// typeShortName returns short package name (e.g. the name x appears in package x definition) dot type name.
func typeShortName(t *types.Type) string {
// `path` vs. `filepath` because packages use '/'
@@ -339,8 +373,18 @@ func (g openAPITypeWriter) generateCall(t *types.Type) error {
// Only generate for struct type and ignore the rest
switch t.Kind {
case types.Struct:
+ if namer.IsPrivateGoName(t.Name.Name) { // skip private types
+ return nil
+ }
+
args := argsFromType(t)
- g.Do("\"$.$\": ", t.Name)
+
+ if g.shouldUseOpenAPIModelName(t) {
+ g.Do("$.|raw${}.OpenAPIModelName(): ", t)
+ } else {
+ // Legacy case: use the "canonical type name"
+ g.Do("\"$.$\": ", t.Name)
+ }
hasV2Definition := hasOpenAPIDefinitionMethod(t)
hasV2DefinitionTypeAndFormat := hasOpenAPIDefinitionMethods(t)
@@ -657,6 +701,9 @@ func (g openAPITypeWriter) generate(t *types.Type) error {
deps := []string{}
for _, k := range keys {
v := g.refTypes[k]
+ if t.Kind != types.Struct {
+ continue
+ }
if t, _ := openapi.OpenAPITypeFormat(v.String()); t != "" {
// This is a known type, we do not need a reference to it
// Will eliminate special case of time.Time
@@ -667,7 +714,12 @@ func (g openAPITypeWriter) generate(t *types.Type) error {
if len(deps) > 0 {
g.Do("Dependencies: []string{\n", args)
for _, k := range deps {
- g.Do("\"$.$\",", k)
+ t := g.refTypes[k]
+ if g.shouldUseOpenAPIModelName(t) {
+ g.Do("$.|raw${}.OpenAPIModelName(),", t)
+ } else {
+ g.Do("\"$.$\",", k)
+ }
}
g.Do("},\n", nil)
}
@@ -1011,8 +1063,10 @@ func (g openAPITypeWriter) generateProperty(m *types.Member, parent *types.Type)
if err := g.generateSliceProperty(t); err != nil {
return fmt.Errorf("failed to generate slice property in %v: %v: %v", parent, m.Name, err)
}
- case types.Struct, types.Interface:
+ case types.Struct:
g.generateReferenceProperty(t)
+ case types.Interface:
+ // Don't generate references to interfaces since we don't declare them
default:
return fmt.Errorf("cannot generate spec for type %v", t)
}
@@ -1027,7 +1081,11 @@ func (g openAPITypeWriter) generateSimpleProperty(typeString, format string) {
func (g openAPITypeWriter) generateReferenceProperty(t *types.Type) {
g.refTypes[t.Name.String()] = t
- g.Do("Ref: ref(\"$.$\"),\n", t.Name.String())
+ if g.shouldUseOpenAPIModelName(t) {
+ g.Do("Ref: ref($.|raw${}.OpenAPIModelName()),\n", t)
+ } else {
+ g.Do("Ref: ref(\"$.$\"),\n", t.Name.String())
+ }
}
func resolvePtrType(t *types.Type) *types.Type {
diff --git a/vendor/k8s.io/kube-openapi/pkg/util/util.go b/vendor/k8s.io/kube-openapi/pkg/util/util.go
index 6eee935b22..830ec3ca09 100644
--- a/vendor/k8s.io/kube-openapi/pkg/util/util.go
+++ b/vendor/k8s.io/kube-openapi/pkg/util/util.go
@@ -92,10 +92,21 @@ type OpenAPICanonicalTypeNamer interface {
OpenAPICanonicalTypeName() string
}
+// OpenAPIModelNamer is an interface Go types may implement to provide an OpenAPI model name.
+//
+// This takes precedence over OpenAPICanonicalTypeNamer, and should be used when a Go type has a model
+// name that differs from its canonical type name as determined by Go package name reflection.
+type OpenAPIModelNamer interface {
+ OpenAPIModelName() string
+}
+
// GetCanonicalTypeName will find the canonical type name of a sample object, removing
// the "vendor" part of the path
func GetCanonicalTypeName(model interface{}) string {
- if namer, ok := model.(OpenAPICanonicalTypeNamer); ok {
+ switch namer := model.(type) {
+ case OpenAPIModelNamer:
+ return namer.OpenAPIModelName()
+ case OpenAPICanonicalTypeNamer:
return namer.OpenAPICanonicalTypeName()
}
t := reflect.TypeOf(model)
diff --git a/vendor/k8s.io/kube-openapi/pkg/validation/strfmt/default.go b/vendor/k8s.io/kube-openapi/pkg/validation/strfmt/default.go
index 97b2f989e9..23109816eb 100644
--- a/vendor/k8s.io/kube-openapi/pkg/validation/strfmt/default.go
+++ b/vendor/k8s.io/kube-openapi/pkg/validation/strfmt/default.go
@@ -17,7 +17,6 @@ package strfmt
import (
"encoding/base64"
"encoding/json"
- "fmt"
"net/mail"
"regexp"
"strings"
@@ -247,29 +246,6 @@ func (b *Base64) UnmarshalText(data []byte) error { // validation is performed l
return nil
}
-// Scan read a value from a database driver
-func (b *Base64) Scan(raw interface{}) error {
- switch v := raw.(type) {
- case []byte:
- dbuf := make([]byte, base64.StdEncoding.DecodedLen(len(v)))
- n, err := base64.StdEncoding.Decode(dbuf, v)
- if err != nil {
- return err
- }
- *b = dbuf[:n]
- case string:
- vv, err := base64.StdEncoding.DecodeString(v)
- if err != nil {
- return err
- }
- *b = Base64(vv)
- default:
- return fmt.Errorf("cannot sql.Scan() strfmt.Base64 from: %#v", v)
- }
-
- return nil
-}
-
func (b Base64) String() string {
return base64.StdEncoding.EncodeToString([]byte(b))
}
@@ -324,20 +300,6 @@ func (u *URI) UnmarshalText(data []byte) error { // validation is performed late
return nil
}
-// Scan read a value from a database driver
-func (u *URI) Scan(raw interface{}) error {
- switch v := raw.(type) {
- case []byte:
- *u = URI(string(v))
- case string:
- *u = URI(v)
- default:
- return fmt.Errorf("cannot sql.Scan() strfmt.URI from: %#v", v)
- }
-
- return nil
-}
-
func (u URI) String() string {
return string(u)
}
@@ -388,20 +350,6 @@ func (e *Email) UnmarshalText(data []byte) error { // validation is performed la
return nil
}
-// Scan read a value from a database driver
-func (e *Email) Scan(raw interface{}) error {
- switch v := raw.(type) {
- case []byte:
- *e = Email(string(v))
- case string:
- *e = Email(v)
- default:
- return fmt.Errorf("cannot sql.Scan() strfmt.Email from: %#v", v)
- }
-
- return nil
-}
-
func (e Email) String() string {
return string(e)
}
@@ -452,20 +400,6 @@ func (h *Hostname) UnmarshalText(data []byte) error { // validation is performed
return nil
}
-// Scan read a value from a database driver
-func (h *Hostname) Scan(raw interface{}) error {
- switch v := raw.(type) {
- case []byte:
- *h = Hostname(string(v))
- case string:
- *h = Hostname(v)
- default:
- return fmt.Errorf("cannot sql.Scan() strfmt.Hostname from: %#v", v)
- }
-
- return nil
-}
-
func (h Hostname) String() string {
return string(h)
}
@@ -516,20 +450,6 @@ func (u *IPv4) UnmarshalText(data []byte) error { // validation is performed lat
return nil
}
-// Scan read a value from a database driver
-func (u *IPv4) Scan(raw interface{}) error {
- switch v := raw.(type) {
- case []byte:
- *u = IPv4(string(v))
- case string:
- *u = IPv4(v)
- default:
- return fmt.Errorf("cannot sql.Scan() strfmt.IPv4 from: %#v", v)
- }
-
- return nil
-}
-
func (u IPv4) String() string {
return string(u)
}
@@ -580,20 +500,6 @@ func (u *IPv6) UnmarshalText(data []byte) error { // validation is performed lat
return nil
}
-// Scan read a value from a database driver
-func (u *IPv6) Scan(raw interface{}) error {
- switch v := raw.(type) {
- case []byte:
- *u = IPv6(string(v))
- case string:
- *u = IPv6(v)
- default:
- return fmt.Errorf("cannot sql.Scan() strfmt.IPv6 from: %#v", v)
- }
-
- return nil
-}
-
func (u IPv6) String() string {
return string(u)
}
@@ -644,20 +550,6 @@ func (u *CIDR) UnmarshalText(data []byte) error { // validation is performed lat
return nil
}
-// Scan read a value from a database driver
-func (u *CIDR) Scan(raw interface{}) error {
- switch v := raw.(type) {
- case []byte:
- *u = CIDR(string(v))
- case string:
- *u = CIDR(v)
- default:
- return fmt.Errorf("cannot sql.Scan() strfmt.CIDR from: %#v", v)
- }
-
- return nil
-}
-
func (u CIDR) String() string {
return string(u)
}
@@ -708,20 +600,6 @@ func (u *MAC) UnmarshalText(data []byte) error { // validation is performed late
return nil
}
-// Scan read a value from a database driver
-func (u *MAC) Scan(raw interface{}) error {
- switch v := raw.(type) {
- case []byte:
- *u = MAC(string(v))
- case string:
- *u = MAC(v)
- default:
- return fmt.Errorf("cannot sql.Scan() strfmt.IPv4 from: %#v", v)
- }
-
- return nil
-}
-
func (u MAC) String() string {
return string(u)
}
@@ -772,20 +650,6 @@ func (u *UUID) UnmarshalText(data []byte) error { // validation is performed lat
return nil
}
-// Scan read a value from a database driver
-func (u *UUID) Scan(raw interface{}) error {
- switch v := raw.(type) {
- case []byte:
- *u = UUID(string(v))
- case string:
- *u = UUID(v)
- default:
- return fmt.Errorf("cannot sql.Scan() strfmt.UUID from: %#v", v)
- }
-
- return nil
-}
-
func (u UUID) String() string {
return string(u)
}
@@ -839,20 +703,6 @@ func (u *UUID3) UnmarshalText(data []byte) error { // validation is performed la
return nil
}
-// Scan read a value from a database driver
-func (u *UUID3) Scan(raw interface{}) error {
- switch v := raw.(type) {
- case []byte:
- *u = UUID3(string(v))
- case string:
- *u = UUID3(v)
- default:
- return fmt.Errorf("cannot sql.Scan() strfmt.UUID3 from: %#v", v)
- }
-
- return nil
-}
-
func (u UUID3) String() string {
return string(u)
}
@@ -906,20 +756,6 @@ func (u *UUID4) UnmarshalText(data []byte) error { // validation is performed la
return nil
}
-// Scan read a value from a database driver
-func (u *UUID4) Scan(raw interface{}) error {
- switch v := raw.(type) {
- case []byte:
- *u = UUID4(string(v))
- case string:
- *u = UUID4(v)
- default:
- return fmt.Errorf("cannot sql.Scan() strfmt.UUID4 from: %#v", v)
- }
-
- return nil
-}
-
func (u UUID4) String() string {
return string(u)
}
@@ -973,20 +809,6 @@ func (u *UUID5) UnmarshalText(data []byte) error { // validation is performed la
return nil
}
-// Scan read a value from a database driver
-func (u *UUID5) Scan(raw interface{}) error {
- switch v := raw.(type) {
- case []byte:
- *u = UUID5(string(v))
- case string:
- *u = UUID5(v)
- default:
- return fmt.Errorf("cannot sql.Scan() strfmt.UUID5 from: %#v", v)
- }
-
- return nil
-}
-
func (u UUID5) String() string {
return string(u)
}
@@ -1040,20 +862,6 @@ func (u *ISBN) UnmarshalText(data []byte) error { // validation is performed lat
return nil
}
-// Scan read a value from a database driver
-func (u *ISBN) Scan(raw interface{}) error {
- switch v := raw.(type) {
- case []byte:
- *u = ISBN(string(v))
- case string:
- *u = ISBN(v)
- default:
- return fmt.Errorf("cannot sql.Scan() strfmt.ISBN from: %#v", v)
- }
-
- return nil
-}
-
func (u ISBN) String() string {
return string(u)
}
@@ -1107,20 +915,6 @@ func (u *ISBN10) UnmarshalText(data []byte) error { // validation is performed l
return nil
}
-// Scan read a value from a database driver
-func (u *ISBN10) Scan(raw interface{}) error {
- switch v := raw.(type) {
- case []byte:
- *u = ISBN10(string(v))
- case string:
- *u = ISBN10(v)
- default:
- return fmt.Errorf("cannot sql.Scan() strfmt.ISBN10 from: %#v", v)
- }
-
- return nil
-}
-
func (u ISBN10) String() string {
return string(u)
}
@@ -1174,20 +968,6 @@ func (u *ISBN13) UnmarshalText(data []byte) error { // validation is performed l
return nil
}
-// Scan read a value from a database driver
-func (u *ISBN13) Scan(raw interface{}) error {
- switch v := raw.(type) {
- case []byte:
- *u = ISBN13(string(v))
- case string:
- *u = ISBN13(v)
- default:
- return fmt.Errorf("cannot sql.Scan() strfmt.ISBN13 from: %#v", v)
- }
-
- return nil
-}
-
func (u ISBN13) String() string {
return string(u)
}
@@ -1241,20 +1021,6 @@ func (u *CreditCard) UnmarshalText(data []byte) error { // validation is perform
return nil
}
-// Scan read a value from a database driver
-func (u *CreditCard) Scan(raw interface{}) error {
- switch v := raw.(type) {
- case []byte:
- *u = CreditCard(string(v))
- case string:
- *u = CreditCard(v)
- default:
- return fmt.Errorf("cannot sql.Scan() strfmt.CreditCard from: %#v", v)
- }
-
- return nil
-}
-
func (u CreditCard) String() string {
return string(u)
}
@@ -1308,20 +1074,6 @@ func (u *SSN) UnmarshalText(data []byte) error { // validation is performed late
return nil
}
-// Scan read a value from a database driver
-func (u *SSN) Scan(raw interface{}) error {
- switch v := raw.(type) {
- case []byte:
- *u = SSN(string(v))
- case string:
- *u = SSN(v)
- default:
- return fmt.Errorf("cannot sql.Scan() strfmt.SSN from: %#v", v)
- }
-
- return nil
-}
-
func (u SSN) String() string {
return string(u)
}
@@ -1375,20 +1127,6 @@ func (h *HexColor) UnmarshalText(data []byte) error { // validation is performed
return nil
}
-// Scan read a value from a database driver
-func (h *HexColor) Scan(raw interface{}) error {
- switch v := raw.(type) {
- case []byte:
- *h = HexColor(string(v))
- case string:
- *h = HexColor(v)
- default:
- return fmt.Errorf("cannot sql.Scan() strfmt.HexColor from: %#v", v)
- }
-
- return nil
-}
-
func (h HexColor) String() string {
return string(h)
}
@@ -1442,20 +1180,6 @@ func (r *RGBColor) UnmarshalText(data []byte) error { // validation is performed
return nil
}
-// Scan read a value from a database driver
-func (r *RGBColor) Scan(raw interface{}) error {
- switch v := raw.(type) {
- case []byte:
- *r = RGBColor(string(v))
- case string:
- *r = RGBColor(v)
- default:
- return fmt.Errorf("cannot sql.Scan() strfmt.RGBColor from: %#v", v)
- }
-
- return nil
-}
-
func (r RGBColor) String() string {
return string(r)
}
@@ -1510,20 +1234,6 @@ func (r *Password) UnmarshalText(data []byte) error { // validation is performed
return nil
}
-// Scan read a value from a database driver
-func (r *Password) Scan(raw interface{}) error {
- switch v := raw.(type) {
- case []byte:
- *r = Password(string(v))
- case string:
- *r = Password(v)
- default:
- return fmt.Errorf("cannot sql.Scan() strfmt.Password from: %#v", v)
- }
-
- return nil
-}
-
func (r Password) String() string {
return string(r)
}
diff --git a/vendor/k8s.io/kube-openapi/pkg/validation/strfmt/duration.go b/vendor/k8s.io/kube-openapi/pkg/validation/strfmt/duration.go
index 8fbeb635fb..04545296bd 100644
--- a/vendor/k8s.io/kube-openapi/pkg/validation/strfmt/duration.go
+++ b/vendor/k8s.io/kube-openapi/pkg/validation/strfmt/duration.go
@@ -119,23 +119,6 @@ func ParseDuration(cand string) (time.Duration, error) {
return 0, fmt.Errorf("unable to parse %s as duration", cand)
}
-// Scan reads a Duration value from database driver type.
-func (d *Duration) Scan(raw interface{}) error {
- switch v := raw.(type) {
- // TODO: case []byte: // ?
- case int64:
- *d = Duration(v)
- case float64:
- *d = Duration(int64(v))
- case nil:
- *d = Duration(0)
- default:
- return fmt.Errorf("cannot sql.Scan() strfmt.Duration from: %#v", v)
- }
-
- return nil
-}
-
// String converts this duration to a string
func (d Duration) String() string {
return time.Duration(d).String()
diff --git a/vendor/k8s.io/kube-openapi/pkg/validation/strfmt/time.go b/vendor/k8s.io/kube-openapi/pkg/validation/strfmt/time.go
index b2324db052..d0fd31a9db 100644
--- a/vendor/k8s.io/kube-openapi/pkg/validation/strfmt/time.go
+++ b/vendor/k8s.io/kube-openapi/pkg/validation/strfmt/time.go
@@ -16,7 +16,6 @@ package strfmt
import (
"encoding/json"
- "fmt"
"regexp"
"strings"
"time"
@@ -114,25 +113,6 @@ func (t *DateTime) UnmarshalText(text []byte) error {
return nil
}
-// Scan scans a DateTime value from database driver type.
-func (t *DateTime) Scan(raw interface{}) error {
- // TODO: case int64: and case float64: ?
- switch v := raw.(type) {
- case []byte:
- return t.UnmarshalText(v)
- case string:
- return t.UnmarshalText([]byte(v))
- case time.Time:
- *t = DateTime(v)
- case nil:
- *t = DateTime{}
- default:
- return fmt.Errorf("cannot sql.Scan() strfmt.DateTime from: %#v", v)
- }
-
- return nil
-}
-
// MarshalJSON returns the DateTime as JSON
func (t DateTime) MarshalJSON() ([]byte, error) {
return json.Marshal(time.Time(t).Format(MarshalFormat))
diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/selinuxwarning/cache/volumecache.go b/vendor/k8s.io/kubernetes/pkg/controller/volume/selinuxwarning/cache/volumecache.go
index dfa129dae9..4b19c985c8 100644
--- a/vendor/k8s.io/kubernetes/pkg/controller/volume/selinuxwarning/cache/volumecache.go
+++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/selinuxwarning/cache/volumecache.go
@@ -114,11 +114,19 @@ func (c *volumeCache) AddVolume(logger klog.Logger, volumeName v1.UniqueVolumeNa
}
// The volume is already known
- // Add the pod to the cache or update its properties
- volume.pods[podKey] = podInfo{
+ podInfo := podInfo{
seLinuxLabel: label,
changePolicy: changePolicy,
}
+ oldPodInfo, found := volume.pods[podKey]
+ if found && oldPodInfo == podInfo {
+ // The Pod is already known too and nothing changed since the last update.
+ // All conflicts were already reported when the Pod was added / updated in the cache last time.
+ return conflicts
+ }
+
+ // Add the updated pod info to the cache
+ volume.pods[podKey] = podInfo
// Emit conflicts for the pod
for otherPodKey, otherPodInfo := range volume.pods {
diff --git a/vendor/k8s.io/kubernetes/pkg/controller/volume/selinuxwarning/selinux_warning_controller.go b/vendor/k8s.io/kubernetes/pkg/controller/volume/selinuxwarning/selinux_warning_controller.go
index e5049e05ab..d373eeabf5 100644
--- a/vendor/k8s.io/kubernetes/pkg/controller/volume/selinuxwarning/selinux_warning_controller.go
+++ b/vendor/k8s.io/kubernetes/pkg/controller/volume/selinuxwarning/selinux_warning_controller.go
@@ -140,9 +140,9 @@ func NewController(
logger := klog.FromContext(ctx)
_, err = podInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
- AddFunc: func(obj interface{}) { c.addPod(logger, obj) },
- DeleteFunc: func(obj interface{}) { c.deletePod(logger, obj) },
- // Not watching updates: Pod volumes and SecurityContext are immutable after creation
+ AddFunc: func(obj interface{}) { c.enqueuePod(logger, obj) },
+ UpdateFunc: func(oldObj, newObj interface{}) { c.updatePod(logger, oldObj, newObj) },
+ DeleteFunc: func(obj interface{}) { c.enqueuePod(logger, obj) },
})
if err != nil {
return nil, err
@@ -178,7 +178,7 @@ func NewController(
return c, nil
}
-func (c *Controller) addPod(_ klog.Logger, obj interface{}) {
+func (c *Controller) enqueuePod(_ klog.Logger, obj interface{}) {
podRef, err := cache.DeletionHandlingObjectToName(obj)
if err != nil {
utilruntime.HandleError(fmt.Errorf("couldn't get key for pod %#v: %w", obj, err))
@@ -186,12 +186,29 @@ func (c *Controller) addPod(_ klog.Logger, obj interface{}) {
c.queue.Add(podRef)
}
-func (c *Controller) deletePod(_ klog.Logger, obj interface{}) {
- podRef, err := cache.DeletionHandlingObjectToName(obj)
- if err != nil {
- utilruntime.HandleError(fmt.Errorf("couldn't get key for pod %#v: %w", obj, err))
+func (c *Controller) updatePod(logger klog.Logger, oldObj, newObj interface{}) {
+ // Pod.Spec fields that are relevant to this controller are immutable after creation (i.e.
+ // pod volumes, SELinux labels, privileged flag). React to update only when the Pod
+ // reaches its final state - kubelet will unmount the Pod volumes and the controller should
+ // therefore remove them from the cache.
+ oldPod, ok := oldObj.(*v1.Pod)
+ if !ok {
+ return
}
- c.queue.Add(podRef)
+ newPod, ok := newObj.(*v1.Pod)
+ if !ok {
+ return
+ }
+
+ // This is an optimization. In theory, passing most pod updates to the controller queue should lead to noop.
+ // To save some CPU, pass only pod updates that can cause any action in the controller
+ if oldPod.Status.Phase == newPod.Status.Phase {
+ return
+ }
+ if newPod.Status.Phase != v1.PodFailed && newPod.Status.Phase != v1.PodSucceeded {
+ return
+ }
+ c.enqueuePod(logger, newObj)
}
func (c *Controller) addPVC(logger klog.Logger, obj interface{}) {
@@ -277,11 +294,7 @@ func (c *Controller) enqueueAllPodsForPVC(logger klog.Logger, namespace, name st
return
}
for _, obj := range objs {
- podRef, err := cache.DeletionHandlingObjectToName(obj)
- if err != nil {
- utilruntime.HandleError(fmt.Errorf("couldn't get key for pod %#v: %w", obj, err))
- }
- c.queue.Add(podRef)
+ c.enqueuePod(logger, obj)
}
}
@@ -401,6 +414,11 @@ func (c *Controller) sync(ctx context.Context, podRef cache.ObjectName) error {
logger.V(5).Info("Error getting pod from informer", "pod", klog.KObj(pod), "podUID", pod.UID, "err", err)
return err
}
+ if pod.Status.Phase == v1.PodFailed || pod.Status.Phase == v1.PodSucceeded {
+ // The pod has reached its final state and kubelet is unmounting is volumes.
+ // Remove them from the cache.
+ return c.syncPodDelete(ctx, podRef)
+ }
return c.syncPod(ctx, pod)
}
@@ -481,8 +499,15 @@ func (c *Controller) syncVolume(logger klog.Logger, pod *v1.Pod, spec *volume.Sp
changePolicy := v1.SELinuxChangePolicyMountOption
if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.SELinuxChangePolicy != nil {
changePolicy = *pod.Spec.SecurityContext.SELinuxChangePolicy
+ logger.V(5).Info("Using Pod SELinux change policy", "pod", klog.KObj(pod), "changePolicy", changePolicy)
}
- if !pluginSupportsSELinuxContextMount {
+ if !pluginSupportsSELinuxContextMount && changePolicy != v1.SELinuxChangePolicyRecursive {
+ logger.V(5).Info("Volume does not support SELinux context mount, setting changePolicy to Recursive", "pod", klog.KObj(pod), "volume", spec.Name())
+ changePolicy = v1.SELinuxChangePolicyRecursive
+ }
+
+ if seLinuxLabel == "" && changePolicy != v1.SELinuxChangePolicyRecursive {
+ logger.V(5).Info("Pod has empty SELinux label, setting changePolicy to Recursive", "pod", klog.KObj(pod))
changePolicy = v1.SELinuxChangePolicyRecursive
}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 9856f5411a..d0109545ba 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -1,6 +1,12 @@
# cel.dev/expr v0.24.0
## explicit; go 1.22.0
cel.dev/expr
+# cyphar.com/go-pathrs v0.2.1
+## explicit; go 1.18
+cyphar.com/go-pathrs
+cyphar.com/go-pathrs/internal/fdutils
+cyphar.com/go-pathrs/internal/libpathrs
+cyphar.com/go-pathrs/procfs
# github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161
## explicit; go 1.16
github.com/Azure/go-ansiterm
@@ -97,7 +103,7 @@ github.com/coreos/go-systemd/daemon
github.com/coreos/go-systemd/v22/daemon
github.com/coreos/go-systemd/v22/dbus
github.com/coreos/go-systemd/v22/journal
-# github.com/cyphar/filepath-securejoin v0.5.1
+# github.com/cyphar/filepath-securejoin v0.6.0
## explicit; go 1.18
github.com/cyphar/filepath-securejoin
github.com/cyphar/filepath-securejoin/internal/consts
@@ -106,6 +112,7 @@ github.com/cyphar/filepath-securejoin/pathrs-lite/internal
github.com/cyphar/filepath-securejoin/pathrs-lite/internal/assert
github.com/cyphar/filepath-securejoin/pathrs-lite/internal/fd
github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gocompat
+github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs
github.com/cyphar/filepath-securejoin/pathrs-lite/internal/kernelversion
github.com/cyphar/filepath-securejoin/pathrs-lite/internal/linux
github.com/cyphar/filepath-securejoin/pathrs-lite/internal/procfs
@@ -288,8 +295,8 @@ github.com/google/go-cmp/cmp/internal/diff
github.com/google/go-cmp/cmp/internal/flags
github.com/google/go-cmp/cmp/internal/function
github.com/google/go-cmp/cmp/internal/value
-# github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad
-## explicit; go 1.22
+# github.com/google/pprof v0.0.0-20250403155104-27863c87afa6
+## explicit; go 1.23
github.com/google/pprof/profile
# github.com/google/uuid v1.6.0
## explicit
@@ -419,7 +426,7 @@ github.com/opencontainers/runc/libcontainer/utils
# github.com/opencontainers/runtime-spec v1.2.0
## explicit
github.com/opencontainers/runtime-spec/specs-go
-# github.com/opencontainers/selinux v1.12.0
+# github.com/opencontainers/selinux v1.13.0
## explicit; go 1.19
github.com/opencontainers/selinux/go-selinux
github.com/opencontainers/selinux/go-selinux/label
@@ -681,7 +688,7 @@ github.com/openshift/cluster-policy-controller/pkg/security/controller
github.com/openshift/cluster-policy-controller/pkg/security/mcs
github.com/openshift/cluster-policy-controller/pkg/security/uidallocator
github.com/openshift/cluster-policy-controller/pkg/version
-# github.com/openshift/library-go v0.0.0-20251112091634-ab97ebb73f0f
+# github.com/openshift/library-go v0.0.0-20260121132910-dc3a1c884c04
## explicit; go 1.24.0
github.com/openshift/library-go/pkg/apiserver/admission/admissionrestconfig
github.com/openshift/library-go/pkg/apiserver/admission/admissiontimeout
@@ -731,8 +738,8 @@ github.com/openshift/library-go/pkg/route/validation
github.com/openshift/library-go/pkg/security/ldaputil
github.com/openshift/library-go/pkg/security/uid
github.com/openshift/library-go/pkg/serviceability
-# github.com/openshift/route-controller-manager v0.0.0-20260127173744-2b9e93a5f0fc
-## explicit; go 1.24.0
+# github.com/openshift/route-controller-manager v0.0.0-20260211095309-624742d93f3a
+## explicit; go 1.25.0
github.com/openshift/route-controller-manager/pkg/cmd/controller
github.com/openshift/route-controller-manager/pkg/cmd/route-controller-manager
github.com/openshift/route-controller-manager/pkg/route/ingress
@@ -797,7 +804,7 @@ github.com/russross/blackfriday/v2
# github.com/sirupsen/logrus v1.9.3
## explicit; go 1.13
github.com/sirupsen/logrus
-# github.com/spf13/cobra v1.9.1
+# github.com/spf13/cobra v1.10.0
## explicit; go 1.15
github.com/spf13/cobra
# github.com/spf13/pflag v1.0.10
@@ -828,8 +835,8 @@ github.com/x448/float16
# github.com/xlab/treeprint v1.2.0
## explicit; go 1.13
github.com/xlab/treeprint
-# go.etcd.io/etcd/api/v3 v3.6.4
-## explicit; go 1.23.0
+# go.etcd.io/etcd/api/v3 v3.6.5
+## explicit; go 1.24
go.etcd.io/etcd/api/v3/authpb
go.etcd.io/etcd/api/v3/etcdserverpb
go.etcd.io/etcd/api/v3/membershippb
@@ -837,8 +844,8 @@ go.etcd.io/etcd/api/v3/mvccpb
go.etcd.io/etcd/api/v3/v3rpc/rpctypes
go.etcd.io/etcd/api/v3/version
go.etcd.io/etcd/api/v3/versionpb
-# go.etcd.io/etcd/client/pkg/v3 v3.6.4
-## explicit; go 1.23.0
+# go.etcd.io/etcd/client/pkg/v3 v3.6.5
+## explicit; go 1.24
go.etcd.io/etcd/client/pkg/v3/fileutil
go.etcd.io/etcd/client/pkg/v3/logutil
go.etcd.io/etcd/client/pkg/v3/systemd
@@ -846,8 +853,8 @@ go.etcd.io/etcd/client/pkg/v3/tlsutil
go.etcd.io/etcd/client/pkg/v3/transport
go.etcd.io/etcd/client/pkg/v3/types
go.etcd.io/etcd/client/pkg/v3/verify
-# go.etcd.io/etcd/client/v3 v3.6.4
-## explicit; go 1.23.0
+# go.etcd.io/etcd/client/v3 v3.6.5
+## explicit; go 1.24
go.etcd.io/etcd/client/v3
go.etcd.io/etcd/client/v3/credentials
go.etcd.io/etcd/client/v3/internal/endpoint
@@ -865,8 +872,8 @@ go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelr
## explicit; go 1.22.0
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/internal
-# go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0
-## explicit; go 1.22.0
+# go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0
+## explicit; go 1.23.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv
@@ -941,13 +948,13 @@ go.uber.org/zap/internal/pool
go.uber.org/zap/internal/stacktrace
go.uber.org/zap/zapcore
go.uber.org/zap/zapgrpc
-# go.yaml.in/yaml/v2 v2.4.2
+# go.yaml.in/yaml/v2 v2.4.3
## explicit; go 1.15
go.yaml.in/yaml/v2
# go.yaml.in/yaml/v3 v3.0.4
## explicit; go 1.16
go.yaml.in/yaml/v3
-# golang.org/x/crypto v0.42.0
+# golang.org/x/crypto v0.45.0
## explicit; go 1.24.0
golang.org/x/crypto/cryptobyte
golang.org/x/crypto/cryptobyte/asn1
@@ -963,13 +970,13 @@ golang.org/x/crypto/salsa20/salsa
## explicit; go 1.20
golang.org/x/exp/constraints
golang.org/x/exp/slices
-# golang.org/x/mod v0.27.0
-## explicit; go 1.23.0
+# golang.org/x/mod v0.29.0
+## explicit; go 1.24.0
golang.org/x/mod/internal/lazyregexp
golang.org/x/mod/module
golang.org/x/mod/semver
-# golang.org/x/net v0.43.0
-## explicit; go 1.23.0
+# golang.org/x/net v0.47.0
+## explicit; go 1.24.0
golang.org/x/net/bpf
golang.org/x/net/context
golang.org/x/net/html
@@ -992,11 +999,11 @@ golang.org/x/net/websocket
## explicit; go 1.23.0
golang.org/x/oauth2
golang.org/x/oauth2/internal
-# golang.org/x/sync v0.17.0
+# golang.org/x/sync v0.18.0
## explicit; go 1.24.0
golang.org/x/sync/errgroup
golang.org/x/sync/singleflight
-# golang.org/x/sys v0.36.0
+# golang.org/x/sys v0.38.0
## explicit; go 1.24.0
golang.org/x/sys/cpu
golang.org/x/sys/plan9
@@ -1005,10 +1012,10 @@ golang.org/x/sys/windows
golang.org/x/sys/windows/registry
golang.org/x/sys/windows/svc
golang.org/x/sys/windows/svc/mgr
-# golang.org/x/term v0.35.0
+# golang.org/x/term v0.37.0
## explicit; go 1.24.0
golang.org/x/term
-# golang.org/x/text v0.29.0
+# golang.org/x/text v0.31.0
## explicit; go 1.24.0
golang.org/x/text/encoding
golang.org/x/text/encoding/internal
@@ -1035,10 +1042,12 @@ golang.org/x/text/unicode/norm
# golang.org/x/time v0.9.0
## explicit; go 1.18
golang.org/x/time/rate
-# golang.org/x/tools v0.36.0
-## explicit; go 1.23.0
+# golang.org/x/tools v0.38.0
+## explicit; go 1.24.0
golang.org/x/tools/container/intsets
golang.org/x/tools/go/ast/astutil
+golang.org/x/tools/go/ast/edge
+golang.org/x/tools/go/ast/inspector
golang.org/x/tools/go/gcexportdata
golang.org/x/tools/go/packages
golang.org/x/tools/go/types/objectpath
@@ -1180,7 +1189,7 @@ google.golang.org/protobuf/types/known/fieldmaskpb
google.golang.org/protobuf/types/known/structpb
google.golang.org/protobuf/types/known/timestamppb
google.golang.org/protobuf/types/known/wrapperspb
-# gopkg.in/evanphx/json-patch.v4 v4.12.0
+# gopkg.in/evanphx/json-patch.v4 v4.13.0
## explicit
gopkg.in/evanphx/json-patch.v4
# gopkg.in/go-jose/go-jose.v2 v2.6.3
@@ -2142,8 +2151,8 @@ k8s.io/kube-aggregator/pkg/registry/apiservice/rest
# k8s.io/kube-controller-manager v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/kube-controller-manager
## explicit; go 1.24.0
k8s.io/kube-controller-manager/config/v1alpha1
-# k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b
-## explicit; go 1.23
+# k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912
+## explicit; go 1.23.0
k8s.io/kube-openapi/cmd/openapi-gen
k8s.io/kube-openapi/cmd/openapi-gen/args
k8s.io/kube-openapi/pkg/aggregator
@@ -2236,7 +2245,7 @@ k8s.io/kubelet/pkg/cri/streaming
k8s.io/kubelet/pkg/cri/streaming/portforward
k8s.io/kubelet/pkg/cri/streaming/remotecommand
k8s.io/kubelet/pkg/types
-# k8s.io/kubernetes v1.34.2 => ./deps/github.com/openshift/kubernetes
+# k8s.io/kubernetes v1.35.0 => ./deps/github.com/openshift/kubernetes
## explicit; go 1.24.0
k8s.io/kubernetes/cmd/kube-apiserver/app
k8s.io/kubernetes/cmd/kube-apiserver/app/options
@@ -3126,7 +3135,7 @@ sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client
sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/metrics
sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/common/metrics
sigs.k8s.io/apiserver-network-proxy/konnectivity-client/proto/client
-# sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8
+# sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730
## explicit; go 1.23
sigs.k8s.io/json
sigs.k8s.io/json/internal/golang/encoding/json
diff --git a/vendor/sigs.k8s.io/json/internal/golang/encoding/json/decode.go b/vendor/sigs.k8s.io/json/internal/golang/encoding/json/decode.go
index d538ac119b..3fe528bbf3 100644
--- a/vendor/sigs.k8s.io/json/internal/golang/encoding/json/decode.go
+++ b/vendor/sigs.k8s.io/json/internal/golang/encoding/json/decode.go
@@ -52,8 +52,8 @@ import (
// - bool, for JSON booleans
// - float64, for JSON numbers
// - string, for JSON strings
-// - []interface{}, for JSON arrays
-// - map[string]interface{}, for JSON objects
+// - []any, for JSON arrays
+// - map[string]any, for JSON objects
// - nil for JSON null
//
// To unmarshal a JSON array into a slice, Unmarshal resets the slice length
@@ -117,9 +117,6 @@ func Unmarshal(data []byte, v any, opts ...UnmarshalOpt) error {
// The input can be assumed to be a valid encoding of
// a JSON value. UnmarshalJSON must copy the JSON data
// if it wishes to retain the data after returning.
-//
-// By convention, to approximate the behavior of [Unmarshal] itself,
-// Unmarshalers implement UnmarshalJSON([]byte("null")) as a no-op.
type Unmarshaler interface {
UnmarshalJSON([]byte) error
}
@@ -132,7 +129,7 @@ type UnmarshalTypeError struct {
Type reflect.Type // type of Go value it could not be assigned to
Offset int64 // error occurred after reading Offset bytes
Struct string // name of the struct type containing the field
- Field string // the full path from root node to the field
+ Field string // the full path from root node to the field, include embedded struct
}
func (e *UnmarshalTypeError) Error() string {
@@ -281,7 +278,11 @@ func (d *decodeState) addErrorContext(err error) error {
switch err := err.(type) {
case *UnmarshalTypeError:
err.Struct = d.errorContext.Struct.Name()
- err.Field = strings.Join(d.errorContext.FieldStack, ".")
+ fieldStack := d.errorContext.FieldStack
+ if err.Field != "" {
+ fieldStack = append(fieldStack, err.Field)
+ }
+ err.Field = strings.Join(fieldStack, ".")
}
}
return err
@@ -492,9 +493,9 @@ func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnm
}
// Prevent infinite loop if v is an interface pointing to its own address:
- // var v interface{}
+ // var v any
// v = &v
- if v.Elem().Kind() == reflect.Interface && v.Elem().Elem() == v {
+ if v.Elem().Kind() == reflect.Interface && v.Elem().Elem().Equal(v) {
v = v.Elem()
break
}
@@ -784,7 +785,10 @@ func (d *decodeState) object(v reflect.Value) error {
}
subv = v
destring = f.quoted
- for _, i := range f.index {
+ if d.errorContext == nil {
+ d.errorContext = new(errorContext)
+ }
+ for i, ind := range f.index {
if subv.Kind() == reflect.Pointer {
if subv.IsNil() {
// If a struct embeds a pointer to an unexported type,
@@ -804,13 +808,16 @@ func (d *decodeState) object(v reflect.Value) error {
}
subv = subv.Elem()
}
- subv = subv.Field(i)
- }
- if d.errorContext == nil {
- d.errorContext = new(errorContext)
+ if i < len(f.index)-1 {
+ d.errorContext.FieldStack = append(
+ d.errorContext.FieldStack,
+ subv.Type().Field(ind).Name,
+ )
+ }
+ subv = subv.Field(ind)
}
- d.errorContext.FieldStack = append(d.errorContext.FieldStack, f.name)
d.errorContext.Struct = t
+ d.errorContext.FieldStack = append(d.errorContext.FieldStack, f.name)
d.appendStrictFieldStackKey(f.name)
} else if d.disallowUnknownFields {
d.saveStrictError(d.newFieldError(unknownStrictErrType, string(key)))
@@ -1118,7 +1125,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
// in an empty interface. They are not strictly necessary,
// but they avoid the weight of reflection in this common case.
-// valueInterface is like value but returns interface{}
+// valueInterface is like value but returns any.
func (d *decodeState) valueInterface() (val any) {
switch d.opcode {
default:
@@ -1135,7 +1142,7 @@ func (d *decodeState) valueInterface() (val any) {
return
}
-// arrayInterface is like array but returns []interface{}.
+// arrayInterface is like array but returns []any.
func (d *decodeState) arrayInterface() []any {
origStrictFieldStackLen := len(d.strictFieldStack)
defer func() {
@@ -1170,7 +1177,7 @@ func (d *decodeState) arrayInterface() []any {
return v
}
-// objectInterface is like object but returns map[string]interface{}.
+// objectInterface is like object but returns map[string]any.
func (d *decodeState) objectInterface() map[string]any {
origStrictFieldStackLen := len(d.strictFieldStack)
defer func() {
diff --git a/vendor/sigs.k8s.io/json/internal/golang/encoding/json/encode.go b/vendor/sigs.k8s.io/json/internal/golang/encoding/json/encode.go
index eb73bff58b..4e3a1a2f10 100644
--- a/vendor/sigs.k8s.io/json/internal/golang/encoding/json/encode.go
+++ b/vendor/sigs.k8s.io/json/internal/golang/encoding/json/encode.go
@@ -71,8 +71,8 @@ import (
//
// The "omitempty" option specifies that the field should be omitted
// from the encoding if the field has an empty value, defined as
-// false, 0, a nil pointer, a nil interface value, and any empty array,
-// slice, map, or string.
+// false, 0, a nil pointer, a nil interface value, and any array,
+// slice, map, or string of length zero.
//
// As a special case, if the field tag is "-", the field is always omitted.
// Note that a field with name "-" can still be generated using the tag "-,".
@@ -98,6 +98,17 @@ import (
// // Field appears in JSON as key "-".
// Field int `json:"-,"`
//
+// The "omitzero" option specifies that the field should be omitted
+// from the encoding if the field has a zero value, according to rules:
+//
+// 1) If the field type has an "IsZero() bool" method, that will be used to
+// determine whether the value is zero.
+//
+// 2) Otherwise, the value is zero if it is the zero value for its type.
+//
+// If both "omitempty" and "omitzero" are specified, the field will be omitted
+// if the value is either empty or zero (or both).
+//
// The "string" option signals that a field is stored as JSON inside a
// JSON-encoded string. It applies only to fields of string, floating point,
// integer, or boolean types. This extra level of encoding is sometimes used
@@ -690,7 +701,8 @@ FieldLoop:
fv = fv.Field(i)
}
- if f.omitEmpty && isEmptyValue(fv) {
+ if (f.omitEmpty && isEmptyValue(fv)) ||
+ (f.omitZero && (f.isZero == nil && fv.IsZero() || (f.isZero != nil && f.isZero(fv)))) {
continue
}
e.WriteByte(next)
@@ -808,7 +820,7 @@ func (se sliceEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
// Here we use a struct to memorize the pointer to the first element of the slice
// and its length.
ptr := struct {
- ptr interface{} // always an unsafe.Pointer, but avoids a dependency on package unsafe
+ ptr any // always an unsafe.Pointer, but avoids a dependency on package unsafe
len int
}{v.UnsafePointer(), v.Len()}
if _, ok := e.ptrSeen[ptr]; ok {
@@ -1039,11 +1051,19 @@ type field struct {
index []int
typ reflect.Type
omitEmpty bool
+ omitZero bool
+ isZero func(reflect.Value) bool
quoted bool
encoder encoderFunc
}
+type isZeroer interface {
+ IsZero() bool
+}
+
+var isZeroerType = reflect.TypeFor[isZeroer]()
+
// typeFields returns a list of fields that JSON should recognize for the given type.
// The algorithm is breadth-first search over the set of structs to include - the top struct
// and then any reachable anonymous structs.
@@ -1135,6 +1155,7 @@ func typeFields(t reflect.Type) structFields {
index: index,
typ: ft,
omitEmpty: opts.Contains("omitempty"),
+ omitZero: opts.Contains("omitzero"),
quoted: quoted,
}
field.nameBytes = []byte(field.name)
@@ -1144,6 +1165,40 @@ func typeFields(t reflect.Type) structFields {
field.nameEscHTML = `"` + string(nameEscBuf) + `":`
field.nameNonEsc = `"` + field.name + `":`
+ if field.omitZero {
+ t := sf.Type
+ // Provide a function that uses a type's IsZero method.
+ switch {
+ case t.Kind() == reflect.Interface && t.Implements(isZeroerType):
+ field.isZero = func(v reflect.Value) bool {
+ // Avoid panics calling IsZero on a nil interface or
+ // non-nil interface with nil pointer.
+ return v.IsNil() ||
+ (v.Elem().Kind() == reflect.Pointer && v.Elem().IsNil()) ||
+ v.Interface().(isZeroer).IsZero()
+ }
+ case t.Kind() == reflect.Pointer && t.Implements(isZeroerType):
+ field.isZero = func(v reflect.Value) bool {
+ // Avoid panics calling IsZero on nil pointer.
+ return v.IsNil() || v.Interface().(isZeroer).IsZero()
+ }
+ case t.Implements(isZeroerType):
+ field.isZero = func(v reflect.Value) bool {
+ return v.Interface().(isZeroer).IsZero()
+ }
+ case reflect.PointerTo(t).Implements(isZeroerType):
+ field.isZero = func(v reflect.Value) bool {
+ if !v.CanAddr() {
+ // Temporarily box v so we can take the address.
+ v2 := reflect.New(v.Type()).Elem()
+ v2.Set(v)
+ v = v2
+ }
+ return v.Addr().Interface().(isZeroer).IsZero()
+ }
+ }
+ }
+
fields = append(fields, field)
if count[f.typ] > 1 {
// If there were multiple instances, add a second,
diff --git a/vendor/sigs.k8s.io/json/internal/golang/encoding/json/stream.go b/vendor/sigs.k8s.io/json/internal/golang/encoding/json/stream.go
index 48fc4d9453..cc2108b927 100644
--- a/vendor/sigs.k8s.io/json/internal/golang/encoding/json/stream.go
+++ b/vendor/sigs.k8s.io/json/internal/golang/encoding/json/stream.go
@@ -31,8 +31,8 @@ func NewDecoder(r io.Reader) *Decoder {
return &Decoder{r: r}
}
-// UseNumber causes the Decoder to unmarshal a number into an interface{} as a
-// [Number] instead of as a float64.
+// UseNumber causes the Decoder to unmarshal a number into an
+// interface value as a [Number] instead of as a float64.
func (dec *Decoder) UseNumber() { dec.d.useNumber = true }
// DisallowUnknownFields causes the Decoder to return an error when the destination